Add support for more resources and single pixel buffers

* 12to11.c (HandleCmdline): Handle `-xrm'.
(XLMain): Initialize single pixel buffers.
* 12to11.man: Improve documentation.
* Imakefile (SRCS): Add single_pixel_buffer.c.
(OBJS): Add single_pixel_buffer.o.
(single-pixel-buffer-v1): Add new scanner target.
* README: Document new supported protocol.
* compositor.h (struct _BufferFuncs): Add single pixel buffer
functions.
* egl.c (enum _EglBufferType): New buffer type.
(struct _EglSinglePixelBuffer): New struct.
(struct _EglBuffr): Add EglSinglePixelBuffer.
(struct _CompositeProgram): Add source_color uniform.
(EglCompileCompositeProgram): Look for both uniforms.
(EglCompileShaders): Compile single pixel shader.
(FindProgram, GetTextureTarget, Composite, UpdateTexture)
(EnsureTexture, UpdateBuffer): Handle single pixel buffers.
(BufferFromSinglePixel, FreeSinglePixelBuffer): New functions.
(egl_buffer_funcs): Add new buffer functions.
* picture_renderer.c (BufferFromSinglePixel,
FreeSinglePixelBuffer): New functions.
(picture_buffer_funcs): Add new buffer functions.
* renderer.c (RenderBufferFromSinglePixel)
(RenderUpdateBufferForDamage): New functions.
(ReadRendererResource, PickRenderer): Read resource if no
environment variable was specified.
* shaders.txt (Composite Rectangle Fragment Shader Single
Pixel): New shader.
* text_input.c (struct _TextInput, UpdatePreedit)
(PreeditStartCallback, PreeditCaretCallback): Correctly handle
caret types and style.
(XLInitTextInput): Fix failure message.
This commit is contained in:
oldosfan 2022-10-06 10:46:54 +00:00
parent a5c7565eb0
commit f2e3baad45
10 changed files with 385 additions and 36 deletions

View file

@ -65,9 +65,10 @@ DetermineServerTime (void)
} }
static void static void
HandleCmdline (int argc, char **argv) HandleCmdline (Display *dpy, int argc, char **argv)
{ {
int i; int i;
XrmDatabase rdb, initial_rdb;
/* Set the default resource and class names. */ /* Set the default resource and class names. */
compositor.resource_name = "12to11"; compositor.resource_name = "12to11";
@ -77,6 +78,9 @@ HandleCmdline (int argc, char **argv)
/* There are no arguments to handle. */ /* There are no arguments to handle. */
return; return;
/* Obtain the resource database. */
initial_rdb = rdb = XrmGetDatabase (dpy);
/* Determine the instance name based on the executable. First, /* Determine the instance name based on the executable. First,
remove any leading directory separator from argv[0]. */ remove any leading directory separator from argv[0]. */
compositor.app_name = strrchr (argv[0], '/'); compositor.app_name = strrchr (argv[0], '/');
@ -94,7 +98,7 @@ HandleCmdline (int argc, char **argv)
{ {
print_usage: print_usage:
fprintf (stderr, fprintf (stderr,
"usage: %s [-name name] [-class class]\n", "usage: %s [-name name] [-class class] [-xrm resourcestring]...\n",
argv[0]); argv[0]);
exit (!strcmp (argv[i], "-help") ? 0 : 1); exit (!strcmp (argv[i], "-help") ? 0 : 1);
} }
@ -120,6 +124,17 @@ HandleCmdline (int argc, char **argv)
compositor.app_name = argv[++i]; compositor.app_name = argv[++i];
} }
else if (!strcmp (argv[i], "-xrm"))
{
if (i + 1 >= argc)
{
fprintf (stderr, "%s: option -xrm requires a value\n",
argv[0]);
exit (1);
}
XrmPutLineResource (&rdb, argv[++i]);
}
else else
{ {
fprintf (stderr, "%s: bad command line option \"%s\"\n", fprintf (stderr, "%s: bad command line option \"%s\"\n",
@ -127,6 +142,11 @@ HandleCmdline (int argc, char **argv)
goto print_usage; goto print_usage;
} }
} }
/* In case XrmPutLineResource created a new database, set it as the
display's resource database. */
if (rdb != initial_rdb)
XrmSetDatabase (dpy, rdb);
} }
static void static void
@ -162,7 +182,7 @@ XLMain (int argc, char **argv)
XGetDefault (dpy, "dummmy", "value"); XGetDefault (dpy, "dummmy", "value");
/* Parse command-line arguments. */ /* Parse command-line arguments. */
HandleCmdline (argc, argv); HandleCmdline (dpy, argc, argv);
compositor.display = dpy; compositor.display = dpy;
compositor.conn = XGetXCBConnection (dpy); compositor.conn = XGetXCBConnection (dpy);
@ -203,6 +223,8 @@ XLMain (int argc, char **argv)
XLInitWpViewporter (); XLInitWpViewporter ();
XLInitDecoration (); XLInitDecoration ();
XLInitTextInput (); XLInitTextInput ();
XLInitSinglePixelBuffer ();
/* This has to come after the rest of the initialization. */ /* This has to come after the rest of the initialization. */
DetermineServerTime (); DetermineServerTime ();
XLRunCompositor (); XLRunCompositor ();

View file

@ -3,7 +3,7 @@
12to11 - Wayland to X protocol translator 12to11 - Wayland to X protocol translator
.SH SYNOPSIS .SH SYNOPSIS
.B 12to11 .B 12to11
[\-\fIclass\fP class] [\-\fIname\fP name] [\-\fBclass\fP \fIclass\fP] [\-\fBname\fP \fIname\fP] [\-\fBxrm\fP \fIresourcestring\fP]...
.SH DESCRIPTION .SH DESCRIPTION
.I 12to11 .I 12to11
starts a Wayland compositor on the next available socket; starts a Wayland compositor on the next available socket;
@ -26,11 +26,16 @@ Wayland clients.
.B \-name \fIname\fP .B \-name \fIname\fP
This option specifies the instance name under which resources are to This option specifies the instance name under which resources are to
be obtained. When not set, it defaults to the executable file name. be obtained. When not set, it defaults to the executable file name.
.TP 8 .TP
.B \-help\fP .B \-help\fP
This option causes the protocol translator to print a message This option causes the protocol translator to print a message
describing options it accepts. The protocol translator will then exit describing options it accepts. The protocol translator will then exit
after printing the message. after printing the message.
.TP
.B \-xrm\fP \fIresourcestring\fP
This option specifies a resource string to be used. This is
especially useful for setting resources that do not have separate
command line options.
.SH RESOURCES .SH RESOURCES
\fI12to11\fP understands some resource names and classes that can be \fI12to11\fP understands some resource names and classes that can be
used to specify various settings that affect its behavior. Those used to specify various settings that affect its behavior. Those
@ -55,26 +60,26 @@ translator.
X input methods can support different editing styles, which affect how X input methods can support different editing styles, which affect how
preconversion and status text is displayed while typing. These styles preconversion and status text is displayed while typing. These styles
are named: are named:
.TP .TP 16
.I overTheSpot .B overTheSpot
In ``over the spot'', the preedit string is displayed in a window In ``over the spot'', the preedit string is displayed in a window
created by the input method at a location specified by the Wayland created by the input method at a location specified by the Wayland
client, typically the text insertion point. client, typically the text insertion point.
.TP .TP
.I offTheSpot .B offTheSpot
In ``off the spot'', the preedit string is displayed in a window In ``off the spot'', the preedit string is displayed in a window
created by the input method at some location away from the text created by the input method at some location away from the text
insertion point. Often, this type of window is placed at the bottom insertion point. Often, this type of window is placed at the bottom
of the preedit window. of the preedit window.
.TP .TP
.I rootWindow .B rootWindow
In the ``root window'' editing style, the preedit string is displayed In the ``root window'' editing style, the preedit string is displayed
in a popup window created by the input method. in a popup window created by the input method.
.TP .TP
.I onTheSpot .B onTheSpot
In the ``on the spot'' editing style, the preedit string is displayed In the ``on the spot'' editing style, the preedit string is displayed
inside the text itself by the Wayland client. inside the text itself by the Wayland client.
.PP .IP "" 8
Not all input methods support all editing styles. In the real world, Not all input methods support all editing styles. In the real world,
most only support one or two of the styles listed above. The protocol most only support one or two of the styles listed above. The protocol
translator will search for a style supported by the input method when translator will search for a style supported by the input method when
@ -82,23 +87,29 @@ initializing input method support. The \fBximStyles\fP resource is
used to control the order in which the protocol translator searches used to control the order in which the protocol translator searches
for input styles, and should be a comma separated list of input names, for input styles, and should be a comma separated list of input names,
which are searched in left-to-right order. For example, which are searched in left-to-right order. For example,
.PP .IP
.in +4 .in +4
.EX .EX
\fBoverTheSpot,rootWindow\fP \fBoverTheSpot,rootWindow\fP
.EE .EE
.in .in
.PP .IP
will result in the protocol translator searching for the ``over the will result in the protocol translator searching for the ``over the
spot'' input style, and if that is not present, the ``root window'' spot'' input style, and if that is not present, the ``root window''
style. Whitespace must not be present inside the comma-separated style. Whitespace must not be present inside the comma-separated
list. When \fBximStyles\fP is not specified, it defaults to: list. When \fBximStyles\fP is not specified, it defaults to:
.PP .IP
.in +4 .in +4
.EX .EX
\fBoverTheSpot,offTheSpot,rootWindow,onTheSpot\fP \fBoverTheSpot,offTheSpot,rootWindow,onTheSpot\fP
.EE .EE
.in .in
.TP
.B renderer \fP (class \fBRenderer\fP)
Specifies the rendering backend the protocol translator uses to
composite the contents of Wayland surfaces onto X windows. This can
either be \fBpicture\fP (the XRender based compositor) or \fBegl\fP
(the OpenGL ES 2.0 based compositor).
.SH ENVIRONMENT .SH ENVIRONMENT
Several environment variables exist that modify the behavior of the Several environment variables exist that modify the behavior of the
protocol translator in one way or another. Most of these are used for protocol translator in one way or another. Most of these are used for
@ -163,12 +174,49 @@ The
variable, if set, controls the rendering backend used by the variable, if set, controls the rendering backend used by the
protocol translator. When set to protocol translator. When set to
.I help .I help
it prints a list of available rendering backends instead. it prints a list of available rendering backends instead. This takes
precedence over the \fBrenderer\fP resource whenever set.
.PP .PP
The The
.B RENDER_VISUAL .B RENDER_VISUAL
variable, if set to a number, contains the ID of the visual used variable, if set to a number, contains the ID of the visual used
when the EGL rendering backend is in use. when the EGL rendering backend is in use.
.SH "CONFORMING TO"
The protocol translator aims to comply with the specifications of the
following Wayland interfaces:
.TS H
lb lb
lb n .
Protocol Version
wl_output 2
wl_compositor 5
wl_shm 1
xdg_wm_base 5
wl_subcompositor 1
wl_seat 7
wl_data_device_manager 3
zwp_linux_dmabuf_v1 4
zwp_primary_selection_device_manager_v1 1
wp_viewporter 1
zxdg_decoration_manager_v1 1
zwp_text_input_manager_v3 1
wp_single_pixel_buffer_manager_v1 1
.TE
.PP
When the protocol translator is built with EGL support, the following
protocol is also supported:
.TS H
lb lb
lb n .
Protocol Version
zwp_linux_explicit_synchronization_v1 2
.TE
.PP
However, Wayland clients are allowed to continue to access data from
the \fBCLIPBOARD\fP and \fBPRIMARY\fP selections even when they do not
have the keyboard focus, against the restrictions put out in the
relevant protocol specifications. It is the opinion of the authors
that such ``security'' does not come with any real benefit.
.SH BUGS .SH BUGS
There is a hard to catch bug where Wayland programs leaving the There is a hard to catch bug where Wayland programs leaving the
fullscreen or maximized state may abruptly return to their maximized fullscreen or maximized state may abruptly return to their maximized
@ -188,6 +236,10 @@ and
.B _NET_WM_STATE .B _NET_WM_STATE
window manager hints will result in Wayland programs running window manager hints will result in Wayland programs running
incorrectly. incorrectly.
.PP
In addition, surfaces transforms are not supported nor reported. The
vast majority of clients seem not to make use of this feature, and
implementing it would be a lot of trouble.
.SH "SEE ALSO" .SH "SEE ALSO"
X(7), Xorg(1) X(7), Xorg(1)
.SH AUTHOR .SH AUTHOR

View file

@ -21,7 +21,8 @@ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c \
dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c \ dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c \
icon_surface.c primary_selection.c renderer.c \ icon_surface.c primary_selection.c renderer.c \
picture_renderer.c explicit_synchronization.c transform.c \ picture_renderer.c explicit_synchronization.c transform.c \
wp_viewporter.c decoration.c text_input.c wp_viewporter.c decoration.c text_input.c \
single_pixel_buffer.c
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
surface.o region.o shm.o atoms.o subcompositor.o positioner.o \ surface.o region.o shm.o atoms.o subcompositor.o positioner.o \
@ -30,7 +31,8 @@ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o \ dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o \
icon_surface.o primary_selection.o renderer.o \ icon_surface.o primary_selection.o renderer.o \
picture_renderer.o explicit_synchronization.o transform.o \ picture_renderer.o explicit_synchronization.o transform.o \
wp_viewporter.o decoration.o text_input.o wp_viewporter.o decoration.o text_input.o \
single_pixel_buffer.o
GENHEADERS = transfer_atoms.h GENHEADERS = transfer_atoms.h
@ -112,6 +114,7 @@ ScannerTarget(linux-explicit-synchronization-unstable-v1)
ScannerTarget(viewporter) ScannerTarget(viewporter)
ScannerTarget(xdg-decoration-unstable-v1) ScannerTarget(xdg-decoration-unstable-v1)
ScannerTarget(text-input-unstable-v3) ScannerTarget(text-input-unstable-v3)
ScannerTarget(single-pixel-buffer-v1)
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */ /* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
$(OBJS): $(GENHEADERS) $(OBJS): $(GENHEADERS)

4
README
View file

@ -50,7 +50,8 @@ for the following EGL and GLES extensions to be present at runtime:
GL_EXT_unpack_subimage GL_EXT_unpack_subimage
After building with EGL support, the renderer must be enabled by After building with EGL support, the renderer must be enabled by
setting the environment variable "RENDERER" to "egl". setting the environment variable "RENDERER" to "egl", or by setting
the "renderer" resource (class "Renderer") to "egl".
The following Wayland protocols are implemented to a more-or-less The following Wayland protocols are implemented to a more-or-less
complete degree: complete degree:
@ -67,6 +68,7 @@ complete degree:
'wp_viewporter', version: 1 'wp_viewporter', version: 1
'zxdg_decoration_manager_v1', version: 1 'zxdg_decoration_manager_v1', version: 1
'zwp_text_input_manager_v3', version: 1 'zwp_text_input_manager_v3', version: 1
'wp_single_pixel_buffer_manager_v1', version: 1
When built with EGL, the following Wayland protocol is also supported: When built with EGL, the following Wayland protocol is also supported:

View file

@ -378,12 +378,19 @@ struct _BufferFuncs
Bool (*validate_shm_params) (uint32_t, uint32_t, uint32_t, int32_t, Bool (*validate_shm_params) (uint32_t, uint32_t, uint32_t, int32_t,
int32_t, size_t); int32_t, size_t);
/* Create a buffer from the given RGBA color. */
RenderBuffer (*buffer_from_single_pixel) (uint32_t, uint32_t, uint32_t, uint32_t,
Bool *);
/* Free a buffer created from shared memory. */ /* Free a buffer created from shared memory. */
void (*free_shm_buffer) (RenderBuffer); void (*free_shm_buffer) (RenderBuffer);
/* Free a dma-buf buffer. */ /* Free a dma-buf buffer. */
void (*free_dmabuf_buffer) (RenderBuffer); void (*free_dmabuf_buffer) (RenderBuffer);
/* Free a single-pixel buffer. */
void (*free_single_pixel_buffer) (RenderBuffer);
/* Notice that the given buffer has been damaged. May be NULL. If /* Notice that the given buffer has been damaged. May be NULL. If
the given NULL damage, assume that the entire buffer has been the given NULL damage, assume that the entire buffer has been
damaged. Must be called at least once before any rendering can damaged. Must be called at least once before any rendering can
@ -435,8 +442,11 @@ extern void RenderBufferFromDmaBufAsync (DmaBufAttributes *, DmaBufSuccessFunc,
extern RenderBuffer RenderBufferFromShm (SharedMemoryAttributes *, Bool *); extern RenderBuffer RenderBufferFromShm (SharedMemoryAttributes *, Bool *);
extern Bool RenderValidateShmParams (uint32_t, uint32_t, uint32_t, int32_t, extern Bool RenderValidateShmParams (uint32_t, uint32_t, uint32_t, int32_t,
int32_t, size_t); int32_t, size_t);
extern RenderBuffer RenderBufferFromSinglePixel (uint32_t, uint32_t, uint32_t,
uint32_t, Bool *);
extern void RenderFreeShmBuffer (RenderBuffer); extern void RenderFreeShmBuffer (RenderBuffer);
extern void RenderFreeDmabufBuffer (RenderBuffer); extern void RenderFreeDmabufBuffer (RenderBuffer);
extern void RenderFreeSinglePixelBuffer (RenderBuffer);
extern void RenderUpdateBufferForDamage (RenderBuffer, pixman_region32_t *, extern void RenderUpdateBufferForDamage (RenderBuffer, pixman_region32_t *,
DrawParams *); DrawParams *);
extern Bool RenderCanReleaseNow (RenderBuffer); extern Bool RenderCanReleaseNow (RenderBuffer);
@ -1463,6 +1473,10 @@ extern void XLWpViewportReportOutOfBuffer (ViewportExt *);
extern void XLInitDecoration (void); extern void XLInitDecoration (void);
/* Defined in single_pixel_buffer.c. */
extern void XLInitSinglePixelBuffer (void);
/* Utility functions that don't belong in a specific file. */ /* Utility functions that don't belong in a specific file. */
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0]) #define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])

142
egl.c
View file

@ -49,6 +49,7 @@ typedef struct _EglBuffer EglBuffer;
typedef struct _EglDmaBufBuffer EglDmaBufBuffer; typedef struct _EglDmaBufBuffer EglDmaBufBuffer;
typedef struct _EglShmBuffer EglShmBuffer; typedef struct _EglShmBuffer EglShmBuffer;
typedef struct _EglSinglePixelBuffer EglSinglePixelBuffer;
typedef struct _FormatInfo FormatInfo; typedef struct _FormatInfo FormatInfo;
typedef struct _CompositeProgram CompositeProgram; typedef struct _CompositeProgram CompositeProgram;
@ -57,6 +58,7 @@ enum _EglBufferType
{ {
DmaBufBuffer, DmaBufBuffer,
ShmBuffer, ShmBuffer,
SinglePixelBuffer,
}; };
struct _EglDmaBufBuffer struct _EglDmaBufBuffer
@ -86,6 +88,15 @@ struct _EglShmBuffer
FormatInfo *format; FormatInfo *format;
}; };
struct _EglSinglePixelBuffer
{
/* The type of this buffer. Always DmaBufBuffer. */
EglBufferType type;
/* The red, green, blue and alpha values. */
float r, g, b, a;
};
struct _FormatInfo struct _FormatInfo
{ {
/* The corresponding Wayland format. */ /* The corresponding Wayland format. */
@ -141,6 +152,9 @@ struct _EglBuffer
/* A shared memory buffer. */ /* A shared memory buffer. */
EglShmBuffer shm; EglShmBuffer shm;
/* A single-pixel buffer. */
EglSinglePixelBuffer single_pixel;
} u; } u;
}; };
@ -190,6 +204,9 @@ struct _CompositeProgram
/* The index of the invert_y uniform. */ /* The index of the invert_y uniform. */
GLuint invert_y; GLuint invert_y;
/* The index of the source_pixel uniform. */
GLuint source_color;
}; };
/* This macro makes column major order easier to reason about for C /* This macro makes column major order easier to reason about for C
@ -387,6 +404,9 @@ static CompositeProgram xrgb_program;
/* Composition program for external textures. */ /* Composition program for external textures. */
static CompositeProgram external_program; static CompositeProgram external_program;
/* Composition program for single pixel buffers. */
static CompositeProgram single_pixel_buffer_program;
/* Whether or not buffer age is supported. */ /* Whether or not buffer age is supported. */
static Bool have_egl_ext_buffer_age; static Bool have_egl_ext_buffer_age;
@ -885,6 +905,8 @@ EglCompileCompositeProgram (CompositeProgram *program,
"source"); "source");
program->invert_y = glGetUniformLocation (program->program, program->invert_y = glGetUniformLocation (program->program,
"invert_y"); "invert_y");
program->source_color = glGetUniformLocation (program->program,
"source_color");
/* Now delete the shaders. */ /* Now delete the shaders. */
glDeleteShader (vertex); glDeleteShader (vertex);
@ -928,6 +950,8 @@ EglCompileShaders (void)
composite_rectangle_fragment_shader_rgbx); composite_rectangle_fragment_shader_rgbx);
EglCompileCompositeProgram (&external_program, EglCompileCompositeProgram (&external_program,
composite_rectangle_fragment_shader_external); composite_rectangle_fragment_shader_external);
EglCompileCompositeProgram (&single_pixel_buffer_program,
composite_rectangle_fragment_shader_single_pixel);
} }
/* Forward declaration. */ /* Forward declaration. */
@ -1276,6 +1300,9 @@ FindProgram (EglBuffer *buffer)
{ {
switch (buffer->u.type) switch (buffer->u.type)
{ {
case SinglePixelBuffer:
/* Use the single-pixel buffer program. */
return &single_pixel_buffer_program;
case DmaBufBuffer: case DmaBufBuffer:
if (buffer->u.dmabuf.format->flags & NeedExternalTarget) if (buffer->u.dmabuf.format->flags & NeedExternalTarget)
/* Use the external format compositor program. */ /* Use the external format compositor program. */
@ -1302,6 +1329,10 @@ GetTextureTarget (EglBuffer *buffer)
case ShmBuffer: case ShmBuffer:
return GL_TEXTURE_2D; return GL_TEXTURE_2D;
default:
/* This should not be called with a single pixel buffer. */
abort ();
} }
/* This is not supposed to happen. */ /* This is not supposed to happen. */
@ -1356,16 +1387,22 @@ Composite (RenderBuffer buffer, RenderTarget target,
egl_target = target.pointer; egl_target = target.pointer;
egl_buffer = buffer.pointer; egl_buffer = buffer.pointer;
/* Assert that a texture was generated, since UpdateBuffer should be if (egl_buffer->u.type != SinglePixelBuffer)
called before the buffer is ever used. */ {
XLAssert (egl_buffer->flags & IsTextureGenerated); /* Assert that a texture was generated, since UpdateBuffer should
be called before the buffer is ever used. */
XLAssert (egl_buffer->flags & IsTextureGenerated);
/* Get the texturing target. */
tex_target = GetTextureTarget (egl_buffer);
}
else
/* This value is not actually used. */
tex_target = 0;
/* Find the program to use for compositing. */ /* Find the program to use for compositing. */
program = FindProgram (egl_buffer); program = FindProgram (egl_buffer);
/* Get the texturing target. */
tex_target = GetTextureTarget (egl_buffer);
/* Compute the transformation matrix to use to draw the given /* Compute the transformation matrix to use to draw the given
buffer. */ buffer. */
ComputeTransformMatrix (egl_buffer, params); ComputeTransformMatrix (egl_buffer, params);
@ -1415,15 +1452,30 @@ Composite (RenderBuffer buffer, RenderTarget target,
else else
glDisable (GL_BLEND); glDisable (GL_BLEND);
glActiveTexture (GL_TEXTURE0); /* Single pixel buffers have no textures. */
glBindTexture (tex_target, egl_buffer->texture); if (egl_buffer->u.type != SinglePixelBuffer)
glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, {
GL_NEAREST); glActiveTexture (GL_TEXTURE0);
glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, glBindTexture (tex_target, egl_buffer->texture);
GL_NEAREST); glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
}
glUseProgram (program->program); glUseProgram (program->program);
glUniform1i (program->texture, 0); /* Single pixel buffers have no textures. */
if (egl_buffer->u.type != SinglePixelBuffer)
glUniform1i (program->texture, 0);
else
/* Attach the source color. */
glUniform4f (program->source_color,
egl_buffer->u.single_pixel.r,
egl_buffer->u.single_pixel.g,
egl_buffer->u.single_pixel.b,
egl_buffer->u.single_pixel.a);
glUniformMatrix3fv (program->source, 1, GL_FALSE, glUniformMatrix3fv (program->source, 1, GL_FALSE,
egl_buffer->matrix); egl_buffer->matrix);
glUniform1i (program->invert_y, egl_buffer->flags & InvertY); glUniform1i (program->invert_y, egl_buffer->flags & InvertY);
@ -1440,7 +1492,9 @@ Composite (RenderBuffer buffer, RenderTarget target,
glDisableVertexAttribArray (program->position); glDisableVertexAttribArray (program->position);
glDisableVertexAttribArray (program->texcoord); glDisableVertexAttribArray (program->texcoord);
glBindTexture (tex_target, 0); /* Single pixel buffers have no textures. */
if (egl_buffer->u.type != SinglePixelBuffer)
glBindTexture (tex_target, 0);
} }
static void static void
@ -1880,6 +1934,35 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
return (RenderBuffer) (void *) buffer; return (RenderBuffer) (void *) buffer;
} }
static RenderBuffer
BufferFromSinglePixel (uint32_t red, uint32_t green, uint32_t blue,
uint32_t alpha, Bool *error)
{
EglBuffer *buffer;
buffer = XLMalloc (EglBufferSize (EglSinglePixelBuffer));
buffer->flags = 0;
buffer->texture = EGL_NO_TEXTURE;
buffer->width = 1;
buffer->height = 1;
buffer->u.type = SinglePixelBuffer;
/* Copy over the identity transform. */
MatrixIdentity (&buffer->matrix);
/* Record the buffer data. */
buffer->u.single_pixel.r = red / (float) 0xffffffff;
buffer->u.single_pixel.g = green / (float) 0xffffffff;
buffer->u.single_pixel.b = blue / (float) 0xffffffff;
buffer->u.single_pixel.a = alpha / (float) 0xffffffff;
/* An alpha channel is present. */
buffer->flags |= HasAlpha;
/* Return the buffer. */
return (RenderBuffer) (void *) buffer;
}
static void static void
FreeShmBuffer (RenderBuffer buffer) FreeShmBuffer (RenderBuffer buffer)
{ {
@ -1911,6 +1994,20 @@ FreeDmabufBuffer (RenderBuffer buffer)
XLFree (buffer.pointer); XLFree (buffer.pointer);
} }
static void
FreeSinglePixelBuffer (RenderBuffer buffer)
{
EglBuffer *egl_buffer;
egl_buffer = buffer.pointer;
/* Make sure a texture was not created. */
XLAssert (egl_buffer->texture == EGL_NO_TEXTURE);
/* Free the wrapper struct. */
XLFree (buffer.pointer);
}
/* Initialization functions. */ /* Initialization functions. */
static void static void
@ -2193,6 +2290,10 @@ UpdateTexture (EglBuffer *buffer)
/* The buffer's been copied to the texture. It can now be /* The buffer's been copied to the texture. It can now be
released. */ released. */
buffer->flags |= CanRelease; buffer->flags |= CanRelease;
break;
default:
break;
} }
/* Bind the target to nothing. */ /* Bind the target to nothing. */
@ -2326,6 +2427,10 @@ EnsureTexture (EglBuffer *buffer)
if (buffer->flags & IsTextureGenerated) if (buffer->flags & IsTextureGenerated)
return; return;
/* If the buffer does not need textures, return. */
if (buffer->u.type == SinglePixelBuffer)
return;
/* Generate the name for the texture. */ /* Generate the name for the texture. */
glGenTextures (1, &buffer->texture); glGenTextures (1, &buffer->texture);
@ -2344,6 +2449,10 @@ UpdateBuffer (RenderBuffer buffer, pixman_region32_t *damage,
egl_buffer = buffer.pointer; egl_buffer = buffer.pointer;
/* Single pixel buffers don't need updates. */
if (egl_buffer->u.type == SinglePixelBuffer)
return;
if (!(egl_buffer->flags & IsTextureGenerated)) if (!(egl_buffer->flags & IsTextureGenerated))
/* No texture has been generated, so just create one and maybe /* No texture has been generated, so just create one and maybe
upload the contents. */ upload the contents. */
@ -2374,6 +2483,9 @@ UpdateBuffer (RenderBuffer buffer, pixman_region32_t *damage,
/* See comment in !damage branch. */ /* See comment in !damage branch. */
UpdateTexture (egl_buffer); UpdateTexture (egl_buffer);
break; break;
default:
break;
} }
} }
} }
@ -2411,8 +2523,10 @@ static BufferFuncs egl_buffer_funcs =
.buffer_from_dma_buf_async = BufferFromDmaBufAsync, .buffer_from_dma_buf_async = BufferFromDmaBufAsync,
.buffer_from_shm = BufferFromShm, .buffer_from_shm = BufferFromShm,
.validate_shm_params = ValidateShmParams, .validate_shm_params = ValidateShmParams,
.buffer_from_single_pixel = BufferFromSinglePixel,
.free_shm_buffer = FreeShmBuffer, .free_shm_buffer = FreeShmBuffer,
.free_dmabuf_buffer = FreeDmabufBuffer, .free_dmabuf_buffer = FreeDmabufBuffer,
.free_single_pixel_buffer = FreeSinglePixelBuffer,
.update_buffer_for_damage = UpdateBufferForDamage, .update_buffer_for_damage = UpdateBufferForDamage,
.can_release_now = CanReleaseNow, .can_release_now = CanReleaseNow,
.init_buffer_funcs = InitBufferFuncs, .init_buffer_funcs = InitBufferFuncs,

View file

@ -1189,6 +1189,45 @@ ValidateShmParams (uint32_t format, uint32_t width, uint32_t height,
return True; return True;
} }
static RenderBuffer
BufferFromSinglePixel (uint32_t red, uint32_t green, uint32_t blue,
uint32_t alpha, Bool *error)
{
Picture picture;
Pixmap pixmap;
XRenderPictureAttributes picture_attrs;
XRenderColor color;
PictureBuffer *buffer;
/* Create the pixmap. */
pixmap = XCreatePixmap (compositor.display,
DefaultRootWindow (compositor.display),
1, 1, compositor.n_planes);
/* Create the picture. */
picture = XRenderCreatePicture (compositor.display, pixmap,
compositor.argb_format, 0,
&picture_attrs);
/* Free the pixmap. */
XFreePixmap (compositor.display, pixmap);
/* Fill the picture with the single pixel. */
color.red = red >> 16;
color.green = green >> 16;
color.blue = blue >> 16;
color.alpha = alpha >> 16;
XRenderFillRectangle (compositor.display, PictOpSrc,
picture, &color, 0, 0, 1, 1);
/* Create the wrapper object. */
buffer = XLCalloc (1, sizeof *buffer);
buffer->picture = picture;
/* Return the picture. */
return (RenderBuffer) (void *) buffer;
}
static void static void
FreeShmBuffer (RenderBuffer buffer) FreeShmBuffer (RenderBuffer buffer)
{ {
@ -1215,6 +1254,18 @@ FreeDmabufBuffer (RenderBuffer buffer)
XLFree (picture_buffer); XLFree (picture_buffer);
} }
static void
FreeSinglePixelBuffer (RenderBuffer buffer)
{
PictureBuffer *picture_buffer;
picture_buffer = buffer.pointer;
XRenderFreePicture (compositor.display,
picture_buffer->picture);
XLFree (picture_buffer);
}
static void static void
SetupMitShm (void) SetupMitShm (void)
{ {
@ -1340,8 +1391,10 @@ static BufferFuncs picture_buffer_funcs =
.buffer_from_dma_buf_async = BufferFromDmaBufAsync, .buffer_from_dma_buf_async = BufferFromDmaBufAsync,
.buffer_from_shm = BufferFromShm, .buffer_from_shm = BufferFromShm,
.validate_shm_params = ValidateShmParams, .validate_shm_params = ValidateShmParams,
.buffer_from_single_pixel = BufferFromSinglePixel,
.free_shm_buffer = FreeShmBuffer, .free_shm_buffer = FreeShmBuffer,
.free_dmabuf_buffer = FreeDmabufBuffer, .free_dmabuf_buffer = FreeDmabufBuffer,
.free_single_pixel_buffer = FreeSinglePixelBuffer,
.can_release_now = CanReleaseNow, .can_release_now = CanReleaseNow,
.init_buffer_funcs = InitBufferFuncs, .init_buffer_funcs = InitBufferFuncs,
}; };

View file

@ -227,6 +227,14 @@ RenderValidateShmParams (uint32_t format, uint32_t width, uint32_t height,
offset, stride, pool_size); offset, stride, pool_size);
} }
RenderBuffer
RenderBufferFromSinglePixel (uint32_t red, uint32_t green, uint32_t blue,
uint32_t alpha, Bool *error)
{
return buffer_funcs.buffer_from_single_pixel (red, green, blue,
alpha, error);
}
void void
RenderFreeShmBuffer (RenderBuffer buffer) RenderFreeShmBuffer (RenderBuffer buffer)
{ {
@ -239,6 +247,12 @@ RenderFreeDmabufBuffer (RenderBuffer buffer)
return buffer_funcs.free_dmabuf_buffer (buffer); return buffer_funcs.free_dmabuf_buffer (buffer);
} }
void
RenderFreeSinglePixelBuffer (RenderBuffer buffer)
{
return buffer_funcs.free_dmabuf_buffer (buffer);
}
void void
RenderUpdateBufferForDamage (RenderBuffer buffer, pixman_region32_t *damage, RenderUpdateBufferForDamage (RenderBuffer buffer, pixman_region32_t *damage,
DrawParams *params) DrawParams *params)
@ -299,6 +313,36 @@ InstallRenderer (Renderer *renderer)
return True; return True;
} }
static const char *
ReadRendererResource (void)
{
XrmDatabase rdb;
XrmName namelist[3];
XrmClass classlist[3];
XrmValue value;
XrmRepresentation type;
rdb = XrmGetDatabase (compositor.display);
if (!rdb)
return NULL;
namelist[1] = XrmStringToQuark ("renderer");
namelist[0] = app_quark;
namelist[2] = NULLQUARK;
classlist[1] = XrmStringToQuark ("Renderer");
classlist[0] = resource_quark;
classlist[2] = NULLQUARK;
if (XrmQGetResource (rdb, namelist, classlist,
&type, &value)
&& type == QString)
return (const char *) value.addr;
return NULL;
}
static void static void
PickRenderer (void) PickRenderer (void)
{ {
@ -310,6 +354,9 @@ PickRenderer (void)
selected = getenv ("RENDERER"); selected = getenv ("RENDERER");
if (!selected)
selected = ReadRendererResource ();
if (selected) if (selected)
{ {
/* If selected is "help", print each renderer and exit. */ /* If selected is "help", print each renderer and exit. */

View file

@ -104,3 +104,30 @@ main (void)
gl_FragColor = texture2D (texture, texcoord); gl_FragColor = texture2D (texture, texcoord);
} }
//== //==
//== Composite Rectangle Fragment Shader Single Pixel
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform vec4 source_color;
uniform mat3 source;
uniform bool invert_y;
varying vec2 v_texcoord;
void
main (void)
{
vec2 texcoord;
texcoord = v_texcoord;
if (invert_y)
texcoord = vec2 (texcoord.x, 1.0 - texcoord.y);
if (texcoord.x < 0.0 || texcoord.y < 0.0
|| texcoord.x > 1.0 || texcoord.y > 1.0)
gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0);
else
gl_FragColor = source_color;
}
//==

View file

@ -177,6 +177,9 @@ struct _TextInput
/* The position of the preedit caret in characters. */ /* The position of the preedit caret in characters. */
int caret; int caret;
/* The style of the caret. */
XIMCaretStyle caret_style;
/* The pending state. */ /* The pending state. */
TextInputState pending_state; TextInputState pending_state;
@ -1437,14 +1440,20 @@ UpdatePreedit (TextInput *input)
goto no_buffer; goto no_buffer;
/* Obtain the caret position. */ /* Obtain the caret position. */
caret = TextPositionFromCharPosition (buffer, new_text_size,
input->caret); if (input->caret_style != XIMIsInvisible)
caret = TextPositionFromCharPosition (buffer, new_text_size,
input->caret);
else
/* The caret is hidden, so don't send any caret position. */
caret.bytepos = -1, caret.charpos = -1;
DebugPrint ("caret position is: char %d, byte: %td", DebugPrint ("caret position is: char %d, byte: %td",
caret.charpos, caret.bytepos); caret.charpos, caret.bytepos);
PreeditString (input, buffer, new_text_size, PreeditString (input, buffer, new_text_size,
/* caret.bytepos will be -1 if obtaining the /* caret.bytepos will be -1 if obtaining the
position failed. */ position failed or the caret is hidden. */
caret.bytepos); caret.bytepos);
XLFree (buffer); XLFree (buffer);
} }
@ -1479,6 +1488,9 @@ PreeditStartCallback (XIC ic, XPointer client_data, XPointer call_data)
/* Create the preedit buffer. */ /* Create the preedit buffer. */
input->buffer = MakePreeditBuffer (locale); input->buffer = MakePreeditBuffer (locale);
/* Set the default caret style. */
input->caret_style = XIMIsPrimary;
/* There should be no limit on the number of bytes in a preedit /* There should be no limit on the number of bytes in a preedit
string. We make the string fit in 4000 bytes ourselves. */ string. We make the string fit in 4000 bytes ourselves. */
return -1; return -1;
@ -1597,6 +1609,9 @@ PreeditCaretCallback (XIC ic, XPointer client_data,
/* Return the caret position. */ /* Return the caret position. */
call_data->position = input->caret; call_data->position = input->caret;
/* Set the caret style. */
input->caret_style = call_data->style;
/* Send change to the client. */ /* Send change to the client. */
UpdatePreedit (input); UpdatePreedit (input);
} }
@ -3381,7 +3396,7 @@ XLInitTextInput (void)
InitInputStyles (); InitInputStyles ();
if (im_fontset == NULL) if (im_fontset == NULL)
fprintf (stderr, "Unable to load any usable fontset for input methods"); fprintf (stderr, "Unable to load any usable fontset for input methods\n");
/* Register the IM callback. */ /* Register the IM callback. */
XRegisterIMInstantiateCallback (compositor.display, XRegisterIMInstantiateCallback (compositor.display,