diff --git a/12to11.c b/12to11.c index b7ddcf0..55e796c 100644 --- a/12to11.c +++ b/12to11.c @@ -65,9 +65,10 @@ DetermineServerTime (void) } static void -HandleCmdline (int argc, char **argv) +HandleCmdline (Display *dpy, int argc, char **argv) { int i; + XrmDatabase rdb, initial_rdb; /* Set the default resource and class names. */ compositor.resource_name = "12to11"; @@ -77,6 +78,9 @@ HandleCmdline (int argc, char **argv) /* There are no arguments to handle. */ return; + /* Obtain the resource database. */ + initial_rdb = rdb = XrmGetDatabase (dpy); + /* Determine the instance name based on the executable. First, remove any leading directory separator from argv[0]. */ compositor.app_name = strrchr (argv[0], '/'); @@ -94,7 +98,7 @@ HandleCmdline (int argc, char **argv) { print_usage: fprintf (stderr, - "usage: %s [-name name] [-class class]\n", + "usage: %s [-name name] [-class class] [-xrm resourcestring]...\n", argv[0]); exit (!strcmp (argv[i], "-help") ? 0 : 1); } @@ -120,6 +124,17 @@ HandleCmdline (int argc, char **argv) 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 { fprintf (stderr, "%s: bad command line option \"%s\"\n", @@ -127,6 +142,11 @@ HandleCmdline (int argc, char **argv) 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 @@ -162,7 +182,7 @@ XLMain (int argc, char **argv) XGetDefault (dpy, "dummmy", "value"); /* Parse command-line arguments. */ - HandleCmdline (argc, argv); + HandleCmdline (dpy, argc, argv); compositor.display = dpy; compositor.conn = XGetXCBConnection (dpy); @@ -203,6 +223,8 @@ XLMain (int argc, char **argv) XLInitWpViewporter (); XLInitDecoration (); XLInitTextInput (); + XLInitSinglePixelBuffer (); + /* This has to come after the rest of the initialization. */ DetermineServerTime (); XLRunCompositor (); diff --git a/12to11.man b/12to11.man index 2331b80..56a4375 100644 --- a/12to11.man +++ b/12to11.man @@ -3,7 +3,7 @@ 12to11 - Wayland to X protocol translator .SH SYNOPSIS .B 12to11 -[\-\fIclass\fP class] [\-\fIname\fP name] +[\-\fBclass\fP \fIclass\fP] [\-\fBname\fP \fIname\fP] [\-\fBxrm\fP \fIresourcestring\fP]... .SH DESCRIPTION .I 12to11 starts a Wayland compositor on the next available socket; @@ -26,11 +26,16 @@ Wayland clients. .B \-name \fIname\fP This option specifies the instance name under which resources are to be obtained. When not set, it defaults to the executable file name. -.TP 8 +.TP .B \-help\fP This option causes the protocol translator to print a message describing options it accepts. The protocol translator will then exit 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 \fI12to11\fP understands some resource names and classes that can be 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 preconversion and status text is displayed while typing. These styles are named: -.TP -.I overTheSpot +.TP 16 +.B overTheSpot In ``over the spot'', the preedit string is displayed in a window created by the input method at a location specified by the Wayland client, typically the text insertion point. .TP -.I offTheSpot +.B offTheSpot In ``off the spot'', the preedit string is displayed in a window created by the input method at some location away from the text insertion point. Often, this type of window is placed at the bottom of the preedit window. .TP -.I rootWindow +.B rootWindow In the ``root window'' editing style, the preedit string is displayed in a popup window created by the input method. .TP -.I onTheSpot +.B onTheSpot In the ``on the spot'' editing style, the preedit string is displayed inside the text itself by the Wayland client. -.PP +.IP "" 8 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 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 for input styles, and should be a comma separated list of input names, which are searched in left-to-right order. For example, -.PP +.IP .in +4 .EX \fBoverTheSpot,rootWindow\fP .EE .in -.PP +.IP will result in the protocol translator searching for the ``over the spot'' input style, and if that is not present, the ``root window'' style. Whitespace must not be present inside the comma-separated list. When \fBximStyles\fP is not specified, it defaults to: -.PP +.IP .in +4 .EX \fBoverTheSpot,offTheSpot,rootWindow,onTheSpot\fP .EE .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 Several environment variables exist that modify the behavior of the 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 protocol translator. When set to .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 The .B RENDER_VISUAL variable, if set to a number, contains the ID of the visual used 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 There is a hard to catch bug where Wayland programs leaving the fullscreen or maximized state may abruptly return to their maximized @@ -188,6 +236,10 @@ and .B _NET_WM_STATE window manager hints will result in Wayland programs running 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" X(7), Xorg(1) .SH AUTHOR diff --git a/Imakefile b/Imakefile index ab01e1c..5d7d2dd 100644 --- a/Imakefile +++ b/Imakefile @@ -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 \ icon_surface.c primary_selection.c renderer.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 \ 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 \ icon_surface.o primary_selection.o renderer.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 @@ -112,6 +114,7 @@ ScannerTarget(linux-explicit-synchronization-unstable-v1) ScannerTarget(viewporter) ScannerTarget(xdg-decoration-unstable-v1) ScannerTarget(text-input-unstable-v3) +ScannerTarget(single-pixel-buffer-v1) /* Make OBJS depend on scanner headers, and depend on both them and SRCS. */ $(OBJS): $(GENHEADERS) diff --git a/README b/README index 6137870..ba49a02 100644 --- a/README +++ b/README @@ -50,7 +50,8 @@ for the following EGL and GLES extensions to be present at runtime: GL_EXT_unpack_subimage 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 complete degree: @@ -67,6 +68,7 @@ complete degree: 'wp_viewporter', version: 1 'zxdg_decoration_manager_v1', 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: diff --git a/compositor.h b/compositor.h index b44e076..e1abbe4 100644 --- a/compositor.h +++ b/compositor.h @@ -378,12 +378,19 @@ struct _BufferFuncs Bool (*validate_shm_params) (uint32_t, uint32_t, uint32_t, int32_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. */ void (*free_shm_buffer) (RenderBuffer); /* Free a dma-buf buffer. */ 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 the given NULL damage, assume that the entire buffer has been 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 Bool RenderValidateShmParams (uint32_t, uint32_t, uint32_t, int32_t, int32_t, size_t); +extern RenderBuffer RenderBufferFromSinglePixel (uint32_t, uint32_t, uint32_t, + uint32_t, Bool *); extern void RenderFreeShmBuffer (RenderBuffer); extern void RenderFreeDmabufBuffer (RenderBuffer); +extern void RenderFreeSinglePixelBuffer (RenderBuffer); extern void RenderUpdateBufferForDamage (RenderBuffer, pixman_region32_t *, DrawParams *); extern Bool RenderCanReleaseNow (RenderBuffer); @@ -1463,6 +1473,10 @@ extern void XLWpViewportReportOutOfBuffer (ViewportExt *); extern void XLInitDecoration (void); +/* Defined in single_pixel_buffer.c. */ + +extern void XLInitSinglePixelBuffer (void); + /* Utility functions that don't belong in a specific file. */ #define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0]) diff --git a/egl.c b/egl.c index 7f8fc09..f4e8b63 100644 --- a/egl.c +++ b/egl.c @@ -49,6 +49,7 @@ typedef struct _EglBuffer EglBuffer; typedef struct _EglDmaBufBuffer EglDmaBufBuffer; typedef struct _EglShmBuffer EglShmBuffer; +typedef struct _EglSinglePixelBuffer EglSinglePixelBuffer; typedef struct _FormatInfo FormatInfo; typedef struct _CompositeProgram CompositeProgram; @@ -57,6 +58,7 @@ enum _EglBufferType { DmaBufBuffer, ShmBuffer, + SinglePixelBuffer, }; struct _EglDmaBufBuffer @@ -86,6 +88,15 @@ struct _EglShmBuffer 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 { /* The corresponding Wayland format. */ @@ -141,6 +152,9 @@ struct _EglBuffer /* A shared memory buffer. */ EglShmBuffer shm; + + /* A single-pixel buffer. */ + EglSinglePixelBuffer single_pixel; } u; }; @@ -190,6 +204,9 @@ struct _CompositeProgram /* The index of the invert_y uniform. */ 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 @@ -387,6 +404,9 @@ static CompositeProgram xrgb_program; /* Composition program for external textures. */ static CompositeProgram external_program; +/* Composition program for single pixel buffers. */ +static CompositeProgram single_pixel_buffer_program; + /* Whether or not buffer age is supported. */ static Bool have_egl_ext_buffer_age; @@ -885,6 +905,8 @@ EglCompileCompositeProgram (CompositeProgram *program, "source"); program->invert_y = glGetUniformLocation (program->program, "invert_y"); + program->source_color = glGetUniformLocation (program->program, + "source_color"); /* Now delete the shaders. */ glDeleteShader (vertex); @@ -928,6 +950,8 @@ EglCompileShaders (void) composite_rectangle_fragment_shader_rgbx); EglCompileCompositeProgram (&external_program, composite_rectangle_fragment_shader_external); + EglCompileCompositeProgram (&single_pixel_buffer_program, + composite_rectangle_fragment_shader_single_pixel); } /* Forward declaration. */ @@ -1276,6 +1300,9 @@ FindProgram (EglBuffer *buffer) { switch (buffer->u.type) { + case SinglePixelBuffer: + /* Use the single-pixel buffer program. */ + return &single_pixel_buffer_program; case DmaBufBuffer: if (buffer->u.dmabuf.format->flags & NeedExternalTarget) /* Use the external format compositor program. */ @@ -1302,6 +1329,10 @@ GetTextureTarget (EglBuffer *buffer) case ShmBuffer: return GL_TEXTURE_2D; + + default: + /* This should not be called with a single pixel buffer. */ + abort (); } /* This is not supposed to happen. */ @@ -1356,16 +1387,22 @@ Composite (RenderBuffer buffer, RenderTarget target, egl_target = target.pointer; egl_buffer = buffer.pointer; - /* Assert that a texture was generated, since UpdateBuffer should be - called before the buffer is ever used. */ - XLAssert (egl_buffer->flags & IsTextureGenerated); + if (egl_buffer->u.type != SinglePixelBuffer) + { + /* 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. */ program = FindProgram (egl_buffer); - /* Get the texturing target. */ - tex_target = GetTextureTarget (egl_buffer); - /* Compute the transformation matrix to use to draw the given buffer. */ ComputeTransformMatrix (egl_buffer, params); @@ -1415,15 +1452,30 @@ Composite (RenderBuffer buffer, RenderTarget target, else glDisable (GL_BLEND); - glActiveTexture (GL_TEXTURE0); - glBindTexture (tex_target, egl_buffer->texture); - glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); + /* Single pixel buffers have no textures. */ + if (egl_buffer->u.type != SinglePixelBuffer) + { + glActiveTexture (GL_TEXTURE0); + glBindTexture (tex_target, egl_buffer->texture); + glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + } + 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, egl_buffer->matrix); glUniform1i (program->invert_y, egl_buffer->flags & InvertY); @@ -1440,7 +1492,9 @@ Composite (RenderBuffer buffer, RenderTarget target, glDisableVertexAttribArray (program->position); 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 @@ -1880,6 +1934,35 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error) 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 FreeShmBuffer (RenderBuffer buffer) { @@ -1911,6 +1994,20 @@ FreeDmabufBuffer (RenderBuffer buffer) 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. */ static void @@ -2193,6 +2290,10 @@ UpdateTexture (EglBuffer *buffer) /* The buffer's been copied to the texture. It can now be released. */ buffer->flags |= CanRelease; + break; + + default: + break; } /* Bind the target to nothing. */ @@ -2326,6 +2427,10 @@ EnsureTexture (EglBuffer *buffer) if (buffer->flags & IsTextureGenerated) return; + /* If the buffer does not need textures, return. */ + if (buffer->u.type == SinglePixelBuffer) + return; + /* Generate the name for the texture. */ glGenTextures (1, &buffer->texture); @@ -2344,6 +2449,10 @@ UpdateBuffer (RenderBuffer buffer, pixman_region32_t *damage, egl_buffer = buffer.pointer; + /* Single pixel buffers don't need updates. */ + if (egl_buffer->u.type == SinglePixelBuffer) + return; + if (!(egl_buffer->flags & IsTextureGenerated)) /* No texture has been generated, so just create one and maybe upload the contents. */ @@ -2374,6 +2483,9 @@ UpdateBuffer (RenderBuffer buffer, pixman_region32_t *damage, /* See comment in !damage branch. */ UpdateTexture (egl_buffer); break; + + default: + break; } } } @@ -2411,8 +2523,10 @@ static BufferFuncs egl_buffer_funcs = .buffer_from_dma_buf_async = BufferFromDmaBufAsync, .buffer_from_shm = BufferFromShm, .validate_shm_params = ValidateShmParams, + .buffer_from_single_pixel = BufferFromSinglePixel, .free_shm_buffer = FreeShmBuffer, .free_dmabuf_buffer = FreeDmabufBuffer, + .free_single_pixel_buffer = FreeSinglePixelBuffer, .update_buffer_for_damage = UpdateBufferForDamage, .can_release_now = CanReleaseNow, .init_buffer_funcs = InitBufferFuncs, diff --git a/picture_renderer.c b/picture_renderer.c index ac63fd6..e3fdd91 100644 --- a/picture_renderer.c +++ b/picture_renderer.c @@ -1189,6 +1189,45 @@ ValidateShmParams (uint32_t format, uint32_t width, uint32_t height, 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 FreeShmBuffer (RenderBuffer buffer) { @@ -1215,6 +1254,18 @@ FreeDmabufBuffer (RenderBuffer 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 SetupMitShm (void) { @@ -1340,8 +1391,10 @@ static BufferFuncs picture_buffer_funcs = .buffer_from_dma_buf_async = BufferFromDmaBufAsync, .buffer_from_shm = BufferFromShm, .validate_shm_params = ValidateShmParams, + .buffer_from_single_pixel = BufferFromSinglePixel, .free_shm_buffer = FreeShmBuffer, .free_dmabuf_buffer = FreeDmabufBuffer, + .free_single_pixel_buffer = FreeSinglePixelBuffer, .can_release_now = CanReleaseNow, .init_buffer_funcs = InitBufferFuncs, }; diff --git a/renderer.c b/renderer.c index 00c7dc4..43fb6ea 100644 --- a/renderer.c +++ b/renderer.c @@ -227,6 +227,14 @@ RenderValidateShmParams (uint32_t format, uint32_t width, uint32_t height, 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 RenderFreeShmBuffer (RenderBuffer buffer) { @@ -239,6 +247,12 @@ RenderFreeDmabufBuffer (RenderBuffer buffer) return buffer_funcs.free_dmabuf_buffer (buffer); } +void +RenderFreeSinglePixelBuffer (RenderBuffer buffer) +{ + return buffer_funcs.free_dmabuf_buffer (buffer); +} + void RenderUpdateBufferForDamage (RenderBuffer buffer, pixman_region32_t *damage, DrawParams *params) @@ -299,6 +313,36 @@ InstallRenderer (Renderer *renderer) 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 PickRenderer (void) { @@ -310,6 +354,9 @@ PickRenderer (void) selected = getenv ("RENDERER"); + if (!selected) + selected = ReadRendererResource (); + if (selected) { /* If selected is "help", print each renderer and exit. */ diff --git a/shaders.txt b/shaders.txt index 9163601..cb99397 100644 --- a/shaders.txt +++ b/shaders.txt @@ -104,3 +104,30 @@ main (void) 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; +} +//== diff --git a/text_input.c b/text_input.c index 9d173ac..ef6d8e4 100644 --- a/text_input.c +++ b/text_input.c @@ -177,6 +177,9 @@ struct _TextInput /* The position of the preedit caret in characters. */ int caret; + /* The style of the caret. */ + XIMCaretStyle caret_style; + /* The pending state. */ TextInputState pending_state; @@ -1437,14 +1440,20 @@ UpdatePreedit (TextInput *input) goto no_buffer; /* 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", caret.charpos, caret.bytepos); PreeditString (input, buffer, new_text_size, /* caret.bytepos will be -1 if obtaining the - position failed. */ + position failed or the caret is hidden. */ caret.bytepos); XLFree (buffer); } @@ -1479,6 +1488,9 @@ PreeditStartCallback (XIC ic, XPointer client_data, XPointer call_data) /* Create the preedit buffer. */ 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 string. We make the string fit in 4000 bytes ourselves. */ return -1; @@ -1597,6 +1609,9 @@ PreeditCaretCallback (XIC ic, XPointer client_data, /* Return the caret position. */ call_data->position = input->caret; + /* Set the caret style. */ + input->caret_style = call_data->style; + /* Send change to the client. */ UpdatePreedit (input); } @@ -3381,7 +3396,7 @@ XLInitTextInput (void) InitInputStyles (); 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. */ XRegisterIMInstantiateCallback (compositor.display,