summaryrefslogtreecommitdiff
path: root/src/gl-renderer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gl-renderer.c')
-rw-r--r--src/gl-renderer.c535
1 files changed, 308 insertions, 227 deletions
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index ae69f220..0e5afbe3 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -50,9 +50,18 @@ struct gl_shader {
#define BUFFER_DAMAGE_COUNT 2
+struct gl_border_image {
+ GLuint tex;
+ int32_t width, height;
+ int32_t tex_width;
+ int dirty;
+ void *data;
+};
+
struct gl_output_state {
EGLSurface egl_surface;
pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
+ struct gl_border_image borders[4];
};
enum buffer_type {
@@ -79,25 +88,25 @@ struct gl_surface_state {
int pitch; /* in pixels */
int height; /* in pixels */
int y_inverted;
+
+ struct weston_surface *surface;
+
+ struct wl_listener surface_destroy_listener;
+ struct wl_listener renderer_destroy_listener;
};
struct gl_renderer {
struct weston_renderer base;
int fragment_shader_debug;
int fan_debug;
+ struct weston_binding *fragment_binding;
+ struct weston_binding *fan_binding;
EGLDisplay egl_display;
EGLContext egl_context;
EGLConfig egl_config;
- struct {
- int32_t top, bottom, left, right;
- GLuint texture;
- int32_t width, height;
- } border;
-
struct wl_array vertices;
- struct wl_array indices; /* only used in compositor-wayland */
struct wl_array vtxcnt;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
@@ -124,6 +133,8 @@ struct gl_renderer {
struct gl_shader invert_color_shader;
struct gl_shader solid_shader;
struct gl_shader *current_shader;
+
+ struct wl_signal destroy_signal;
};
static inline struct gl_output_state *
@@ -132,9 +143,15 @@ get_output_state(struct weston_output *output)
return (struct gl_output_state *)output->renderer_state;
}
+static int
+gl_renderer_create_surface(struct weston_surface *surface);
+
static inline struct gl_surface_state *
get_surface_state(struct weston_surface *surface)
{
+ if (!surface->renderer_state)
+ gl_renderer_create_surface(surface);
+
return (struct gl_surface_state *)surface->renderer_state;
}
@@ -170,7 +187,7 @@ egl_error_string(EGLint code)
#undef MYERRCODE
}
-WL_EXPORT void
+static void
gl_renderer_print_egl_error_state(void)
{
EGLint code;
@@ -193,7 +210,7 @@ gl_renderer_print_egl_error_state(void)
* polygon area.
*/
static int
-calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
+calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
{
@@ -213,8 +230,8 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
/* transform surface to screen space: */
for (i = 0; i < surf.n; i++)
- weston_surface_to_global_float(es, surf.x[i], surf.y[i],
- &surf.x[i], &surf.y[i]);
+ weston_view_to_global_float(ev, surf.x[i], surf.y[i],
+ &surf.x[i], &surf.y[i]);
/* find bounding box: */
min_x = max_x = surf.x[0];
@@ -238,9 +255,8 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
* there will be only four edges. We just need to clip the surface
* vertices to the clip rect bounds:
*/
- if (!es->transform.enabled) {
+ if (!ev->transform.enabled)
return clip_simple(&ctx, &surf, ex, ey);
- }
/* Transformed case: use a general polygon clipping algorithm to
* clip the surface rectangle with each side of 'rect'.
@@ -257,11 +273,11 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
}
static int
-texture_region(struct weston_surface *es, pixman_region32_t *region,
+texture_region(struct weston_view *ev, pixman_region32_t *region,
pixman_region32_t *surf_region)
{
- struct gl_surface_state *gs = get_surface_state(es);
- struct weston_compositor *ec = es->compositor;
+ struct gl_surface_state *gs = get_surface_state(ev->surface);
+ struct weston_compositor *ec = ev->surface->compositor;
struct gl_renderer *gr = get_renderer(ec);
GLfloat *v, inv_width, inv_height;
unsigned int *vtxcnt, nvtx = 0;
@@ -302,18 +318,20 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
* form the intersection of the clip rect and the transformed
* surface.
*/
- n = calculate_edges(es, rect, surf_rect, ex, ey);
+ n = calculate_edges(ev, rect, surf_rect, ex, ey);
if (n < 3)
continue;
/* emit edge points: */
for (k = 0; k < n; k++) {
- weston_surface_from_global_float(es, ex[k], ey[k], &sx, &sy);
+ weston_view_from_global_float(ev, ex[k], ey[k],
+ &sx, &sy);
/* position: */
*(v++) = ex[k];
*(v++) = ey[k];
/* texcoord: */
- weston_surface_to_buffer_float(es, sx, sy,
+ weston_surface_to_buffer_float(ev->surface,
+ sx, sy,
&bx, &by);
*(v++) = bx * inv_width;
if (gs->y_inverted) {
@@ -331,9 +349,9 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
}
static void
-triangle_fan_debug(struct weston_surface *surface, int first, int count)
+triangle_fan_debug(struct weston_view *view, int first, int count)
{
- struct weston_compositor *compositor = surface->compositor;
+ struct weston_compositor *compositor = view->surface->compositor;
struct gl_renderer *gr = get_renderer(compositor);
int i;
GLushort *buffer;
@@ -371,10 +389,10 @@ triangle_fan_debug(struct weston_surface *surface, int first, int count)
}
static void
-repaint_region(struct weston_surface *es, pixman_region32_t *region,
+repaint_region(struct weston_view *ev, pixman_region32_t *region,
pixman_region32_t *surf_region)
{
- struct weston_compositor *ec = es->compositor;
+ struct weston_compositor *ec = ev->surface->compositor;
struct gl_renderer *gr = get_renderer(ec);
GLfloat *v;
unsigned int *vtxcnt;
@@ -388,7 +406,7 @@ repaint_region(struct weston_surface *es, pixman_region32_t *region,
* polygon for each pair, and store it as a triangle fan if
* it has a non-zero area (at least 3 vertices1, actually).
*/
- nfans = texture_region(es, region, surf_region);
+ nfans = texture_region(ev, region, surf_region);
v = gr->vertices.data;
vtxcnt = gr->vtxcnt.data;
@@ -404,7 +422,7 @@ repaint_region(struct weston_surface *es, pixman_region32_t *region,
for (i = 0, first = 0; i < nfans; i++) {
glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
if (gr->fan_debug)
- triangle_fan_debug(es, first, vtxcnt[i]);
+ triangle_fan_debug(ev, first, vtxcnt[i]);
first += vtxcnt[i];
}
@@ -464,28 +482,28 @@ use_shader(struct gl_renderer *gr, struct gl_shader *shader)
static void
shader_uniforms(struct gl_shader *shader,
- struct weston_surface *surface,
- struct weston_output *output)
+ struct weston_view *view,
+ struct weston_output *output)
{
int i;
- struct gl_surface_state *gs = get_surface_state(surface);
+ struct gl_surface_state *gs = get_surface_state(view->surface);
glUniformMatrix4fv(shader->proj_uniform,
1, GL_FALSE, output->matrix.d);
glUniform4fv(shader->color_uniform, 1, gs->color);
- glUniform1f(shader->alpha_uniform, surface->alpha);
+ glUniform1f(shader->alpha_uniform, view->alpha);
for (i = 0; i < gs->num_textures; i++)
glUniform1i(shader->tex_uniforms[i], i);
}
static void
-draw_surface(struct weston_surface *es, struct weston_output *output,
- pixman_region32_t *damage) /* in global coordinates */
+draw_view(struct weston_view *ev, struct weston_output *output,
+ pixman_region32_t *damage) /* in global coordinates */
{
- struct weston_compositor *ec = es->compositor;
+ struct weston_compositor *ec = ev->surface->compositor;
struct gl_renderer *gr = get_renderer(ec);
- struct gl_surface_state *gs = get_surface_state(es);
+ struct gl_surface_state *gs = get_surface_state(ev->surface);
/* repaint bounding region in global coordinates: */
pixman_region32_t repaint;
/* non-opaque region in surface coordinates: */
@@ -493,10 +511,16 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
GLint filter;
int i;
+ /* In case of a runtime switch of renderers, we may not have received
+ * an attach for this surface since the switch. In that case we don't
+ * have a valid buffer or a proper shader set up so skip rendering. */
+ if (!gs->shader)
+ return;
+
pixman_region32_init(&repaint);
pixman_region32_intersect(&repaint,
- &es->transform.boundingbox, damage);
- pixman_region32_subtract(&repaint, &repaint, &es->clip);
+ &ev->transform.boundingbox, damage);
+ pixman_region32_subtract(&repaint, &repaint, &ev->clip);
if (!pixman_region32_not_empty(&repaint))
goto out;
@@ -505,13 +529,14 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
if (gr->fan_debug) {
use_shader(gr, &gr->solid_shader);
- shader_uniforms(&gr->solid_shader, es, output);
+ shader_uniforms(&gr->solid_shader, ev, output);
}
use_shader(gr, gs->shader);
- shader_uniforms(gs->shader, es, output);
+ shader_uniforms(gs->shader, ev, output);
- if (es->transform.enabled || output->zoom.active || output->current_scale != es->buffer_scale)
+ if (ev->transform.enabled || output->zoom.active ||
+ output->current_scale != ev->surface->buffer_viewport.scale)
filter = GL_LINEAR;
else
filter = GL_NEAREST;
@@ -525,10 +550,11 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
/* blended region is whole surface minus opaque region: */
pixman_region32_init_rect(&surface_blend, 0, 0,
- es->geometry.width, es->geometry.height);
- pixman_region32_subtract(&surface_blend, &surface_blend, &es->opaque);
+ ev->surface->width, ev->surface->height);
+ pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
- if (pixman_region32_not_empty(&es->opaque)) {
+ /* XXX: Should we be using ev->transform.opaque here? */
+ if (pixman_region32_not_empty(&ev->surface->opaque)) {
if (gs->shader == &gr->texture_shader_rgba) {
/* Special case for RGBA textures with possibly
* bad data in alpha channel: use the shader
@@ -536,21 +562,21 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
* Xwayland surfaces need this.
*/
use_shader(gr, &gr->texture_shader_rgbx);
- shader_uniforms(&gr->texture_shader_rgbx, es, output);
+ shader_uniforms(&gr->texture_shader_rgbx, ev, output);
}
- if (es->alpha < 1.0)
+ if (ev->alpha < 1.0)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
- repaint_region(es, &repaint, &es->opaque);
+ repaint_region(ev, &repaint, &ev->surface->opaque);
}
if (pixman_region32_not_empty(&surface_blend)) {
use_shader(gr, gs->shader);
glEnable(GL_BLEND);
- repaint_region(es, &repaint, &surface_blend);
+ repaint_region(ev, &repaint, &surface_blend);
}
pixman_region32_fini(&surface_blend);
@@ -560,130 +586,128 @@ out:
}
static void
-repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
+repaint_views(struct weston_output *output, pixman_region32_t *damage)
{
struct weston_compositor *compositor = output->compositor;
- struct weston_surface *surface;
+ struct weston_view *view;
- wl_list_for_each_reverse(surface, &compositor->surface_list, link)
- if (surface->plane == &compositor->primary_plane)
- draw_surface(surface, output, damage);
+ wl_list_for_each_reverse(view, &compositor->view_list, link)
+ if (view->plane == &compositor->primary_plane)
+ draw_view(view, output, damage);
}
-
-static int
-texture_border(struct weston_output *output)
+static void
+draw_output_border_texture(struct gl_border_image *img, int32_t x, int32_t y,
+ int32_t width, int32_t height)
{
- struct weston_compositor *ec = output->compositor;
- struct gl_renderer *gr = get_renderer(ec);
- GLfloat *d;
- unsigned short *p;
- int i, j, k, n;
- GLfloat x[4], y[4], u[4], v[4];
-
- x[0] = -gr->border.left;
- x[1] = 0;
- x[2] = output->current_mode->width;
- x[3] = output->current_mode->width + gr->border.right;
-
- y[0] = -gr->border.top;
- y[1] = 0;
- y[2] = output->current_mode->height;
- y[3] = output->current_mode->height + gr->border.bottom;
-
- u[0] = 0.0;
- u[1] = (GLfloat) gr->border.left / gr->border.width;
- u[2] = (GLfloat) (gr->border.width - gr->border.right) / gr->border.width;
- u[3] = 1.0;
-
- v[0] = 0.0;
- v[1] = (GLfloat) gr->border.top / gr->border.height;
- v[2] = (GLfloat) (gr->border.height - gr->border.bottom) / gr->border.height;
- v[3] = 1.0;
-
- n = 8;
- d = wl_array_add(&gr->vertices, n * 16 * sizeof *d);
- p = wl_array_add(&gr->indices, n * 6 * sizeof *p);
-
- k = 0;
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++) {
-
- if (i == 1 && j == 1)
- continue;
+ static GLushort indices [] = { 0, 1, 3, 3, 1, 2 };
- d[ 0] = x[i];
- d[ 1] = y[j];
- d[ 2] = u[i];
- d[ 3] = v[j];
-
- d[ 4] = x[i];
- d[ 5] = y[j + 1];
- d[ 6] = u[i];
- d[ 7] = v[j + 1];
-
- d[ 8] = x[i + 1];
- d[ 9] = y[j];
- d[10] = u[i + 1];
- d[11] = v[j];
-
- d[12] = x[i + 1];
- d[13] = y[j + 1];
- d[14] = u[i + 1];
- d[15] = v[j + 1];
-
- p[0] = k + 0;
- p[1] = k + 1;
- p[2] = k + 2;
- p[3] = k + 2;
- p[4] = k + 1;
- p[5] = k + 3;
-
- d += 16;
- p += 6;
- k += 4;
+ if (!img->data) {
+ if (img->tex) {
+ glDeleteTextures(1, &img->tex);
+ img->tex = 0;
}
- return k / 4;
+ return;
+ }
+
+ if (!img->tex) {
+ glGenTextures(1, &img->tex);
+ glBindTexture(GL_TEXTURE_2D, img->tex);
+
+ glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, img->tex);
+ }
+
+ if (img->dirty) {
+#ifdef GL_EXT_unpack_subimage
+ glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
+#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
+ img->tex_width, img->height, 0,
+ GL_BGRA_EXT, GL_UNSIGNED_BYTE, img->data);
+ img->dirty = 0;
+ }
+
+ GLfloat texcoord[] = {
+ 0.0f, 0.0f,
+ (GLfloat)img->width / (GLfloat)img->tex_width, 0.0f,
+ (GLfloat)img->width / (GLfloat)img->tex_width, 1.0f,
+ 0.0f, 1.0f,
+ };
+
+ GLfloat verts[] = {
+ x, y,
+ x + width, y,
+ x + width, y + height,
+ x, y + height
+ };
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+ glDisableVertexAttribArray(1);
+ glDisableVertexAttribArray(0);
}
static void
-draw_border(struct weston_output *output)
+draw_output_border(struct weston_output *output)
{
- struct weston_compositor *ec = output->compositor;
- struct gl_renderer *gr = get_renderer(ec);
+ struct gl_output_state *go = get_output_state(output);
+ struct gl_renderer *gr = get_renderer(output->compositor);
struct gl_shader *shader = &gr->texture_shader_rgba;
- GLfloat *v;
- int n;
+ struct gl_border_image *top, *bottom, *left, *right;
+ struct weston_matrix matrix;
+ int full_width, full_height;
+
+ top = &go->borders[GL_RENDERER_BORDER_TOP];
+ bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
+ left = &go->borders[GL_RENDERER_BORDER_LEFT];
+ right = &go->borders[GL_RENDERER_BORDER_RIGHT];
+
+ full_width = output->current_mode->width + left->width + right->width;
+ full_height = output->current_mode->height + top->height + bottom->height;
glDisable(GL_BLEND);
use_shader(gr, shader);
- glUniformMatrix4fv(shader->proj_uniform,
- 1, GL_FALSE, output->matrix.d);
+ glViewport(0, 0, full_width, full_height);
+
+ weston_matrix_init(&matrix);
+ weston_matrix_translate(&matrix, -full_width/2.0, -full_height/2.0, 0);
+ weston_matrix_scale(&matrix, 2.0/full_width, -2.0/full_height, 1);
+ glUniformMatrix4fv(shader->proj_uniform, 1, GL_FALSE, matrix.d);
glUniform1i(shader->tex_uniforms[0], 0);
glUniform1f(shader->alpha_uniform, 1);
-
- n = texture_border(output);
-
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, gr->border.texture);
- v = gr->vertices.data;
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
-
- glDrawElements(GL_TRIANGLES, n * 6,
- GL_UNSIGNED_SHORT, gr->indices.data);
-
- glDisableVertexAttribArray(1);
- glDisableVertexAttribArray(0);
-
- gr->vertices.size = 0;
- gr->indices.size = 0;
+ draw_output_border_texture(top,
+ 0, 0,
+ full_width, top->height);
+ draw_output_border_texture(left,
+ 0, top->height,
+ left->width, output->current_mode->height);
+ draw_output_border_texture(right,
+ full_width - right->width, top->height,
+ right->width, output->current_mode->height);
+ draw_output_border_texture(bottom,
+ 0, full_height - bottom->height,
+ full_width, bottom->height);
}
static void
@@ -740,15 +764,13 @@ gl_renderer_repaint_output(struct weston_output *output,
struct gl_renderer *gr = get_renderer(compositor);
EGLBoolean ret;
static int errored;
- int32_t width, height;
pixman_region32_t buffer_damage, total_damage;
- width = output->current_mode->width +
- output->border.left + output->border.right;
- height = output->current_mode->height +
- output->border.top + output->border.bottom;
-
- glViewport(0, 0, width, height);
+ /* Calculate the viewport */
+ glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width,
+ go->borders[GL_RENDERER_BORDER_BOTTOM].height,
+ output->current_mode->width,
+ output->current_mode->height);
if (use_output(output) < 0)
return;
@@ -762,7 +784,7 @@ gl_renderer_repaint_output(struct weston_output *output,
pixman_region32_subtract(&undamaged, &output->region,
output_damage);
gr->fan_debug = 0;
- repaint_surfaces(output, &undamaged);
+ repaint_views(output, &undamaged);
gr->fan_debug = 1;
pixman_region32_fini(&undamaged);
}
@@ -775,13 +797,12 @@ gl_renderer_repaint_output(struct weston_output *output,
pixman_region32_union(&total_damage, &buffer_damage, output_damage);
- repaint_surfaces(output, &total_damage);
+ repaint_views(output, &total_damage);
pixman_region32_fini(&total_damage);
pixman_region32_fini(&buffer_damage);
- if (gr->border.texture)
- draw_border(output);
+ draw_output_border(output);
pixman_region32_copy(&output->previous_damage, output_damage);
wl_signal_emit(&output->frame_signal, output);
@@ -830,6 +851,8 @@ gl_renderer_flush_damage(struct weston_surface *surface)
struct gl_renderer *gr = get_renderer(surface->compositor);
struct gl_surface_state *gs = get_surface_state(surface);
struct weston_buffer *buffer = gs->buffer_ref.buffer;
+ struct weston_view *view;
+ int texture_used;
GLenum format;
int pixel_type;
@@ -850,10 +873,18 @@ gl_renderer_flush_damage(struct weston_surface *surface)
* hold the reference to the buffer, in case the surface
* migrates back to the primary plane.
*/
- if (surface->plane != &surface->compositor->primary_plane)
+ texture_used = 0;
+ wl_list_for_each(view, &surface->views, surface_link) {
+ if (view->plane == &surface->compositor->primary_plane) {
+ texture_used = 1;
+ break;
+ }
+ }
+ if (!texture_used)
return;
- if (!pixman_region32_not_empty(&gs->texture_damage))
+ if (!pixman_region32_not_empty(&gs->texture_damage) &&
+ !gs->needs_full_upload)
goto done;
switch (wl_shm_buffer_get_format(buffer->shm_buffer)) {
@@ -875,10 +906,12 @@ gl_renderer_flush_damage(struct weston_surface *surface)
glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
if (!gr->has_unpack_subimage) {
+ wl_shm_buffer_begin_access(buffer->shm_buffer);
glTexImage2D(GL_TEXTURE_2D, 0, format,
gs->pitch, buffer->height, 0,
format, pixel_type,
wl_shm_buffer_get_data(buffer->shm_buffer));
+ wl_shm_buffer_end_access(buffer->shm_buffer);
goto done;
}
@@ -890,13 +923,16 @@ gl_renderer_flush_damage(struct weston_surface *surface)
if (gs->needs_full_upload) {
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
+ wl_shm_buffer_begin_access(buffer->shm_buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, gs->pitch, buffer->height,
format, pixel_type, data);
+ wl_shm_buffer_end_access(buffer->shm_buffer);
goto done;
}
rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
+ wl_shm_buffer_begin_access(buffer->shm_buffer);
for (i = 0; i < n; i++) {
pixman_box32_t r;
@@ -908,6 +944,7 @@ gl_renderer_flush_damage(struct weston_surface *surface)
r.x2 - r.x1, r.y2 - r.y1,
format, pixel_type, data);
}
+ wl_shm_buffer_end_access(buffer->shm_buffer);
#endif
done:
@@ -983,6 +1020,8 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
gs->needs_full_upload = 1;
gs->y_inverted = 1;
+ gs->surface = es;
+
ensure_textures(gs, 1);
glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
@@ -1122,10 +1161,59 @@ gl_renderer_surface_set_color(struct weston_surface *surface,
gs->shader = &gr->solid_shader;
}
+static void
+surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
+{
+ int i;
+
+ wl_list_remove(&gs->surface_destroy_listener.link);
+ wl_list_remove(&gs->renderer_destroy_listener.link);
+
+ gs->surface->renderer_state = NULL;
+
+ glDeleteTextures(gs->num_textures, gs->textures);
+
+ for (i = 0; i < gs->num_images; i++)
+ gr->destroy_image(gr->egl_display, gs->images[i]);
+
+ weston_buffer_reference(&gs->buffer_ref, NULL);
+ pixman_region32_fini(&gs->texture_damage);
+ free(gs);
+}
+
+static void
+surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
+{
+ struct gl_surface_state *gs;
+ struct gl_renderer *gr;
+
+ gs = container_of(listener, struct gl_surface_state,
+ surface_destroy_listener);
+
+ gr = get_renderer(gs->surface->compositor);
+
+ surface_state_destroy(gs, gr);
+}
+
+static void
+surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
+{
+ struct gl_surface_state *gs;
+ struct gl_renderer *gr;
+
+ gr = data;
+
+ gs = container_of(listener, struct gl_surface_state,
+ renderer_destroy_listener);
+
+ surface_state_destroy(gs, gr);
+}
+
static int
gl_renderer_create_surface(struct weston_surface *surface)
{
struct gl_surface_state *gs;
+ struct gl_renderer *gr = get_renderer(surface->compositor);
gs = calloc(1, sizeof *gs);
if (!gs)
@@ -1138,27 +1226,27 @@ gl_renderer_create_surface(struct weston_surface *surface)
gs->pitch = 1;
gs->y_inverted = 1;
+ gs->surface = surface;
+
pixman_region32_init(&gs->texture_damage);
surface->renderer_state = gs;
- return 0;
-}
-
-static void
-gl_renderer_destroy_surface(struct weston_surface *surface)
-{
- struct gl_surface_state *gs = get_surface_state(surface);
- struct gl_renderer *gr = get_renderer(surface->compositor);
- int i;
+ gs->surface_destroy_listener.notify =
+ surface_state_handle_surface_destroy;
+ wl_signal_add(&surface->destroy_signal,
+ &gs->surface_destroy_listener);
- glDeleteTextures(gs->num_textures, gs->textures);
+ gs->renderer_destroy_listener.notify =
+ surface_state_handle_renderer_destroy;
+ wl_signal_add(&gr->destroy_signal,
+ &gs->renderer_destroy_listener);
- for (i = 0; i < gs->num_images; i++)
- gr->destroy_image(gr->egl_display, gs->images[i]);
+ if (surface->buffer_ref.buffer) {
+ gl_renderer_attach(surface, surface->buffer_ref.buffer);
+ gl_renderer_flush_damage(surface);
+ }
- weston_buffer_reference(&gs->buffer_ref, NULL);
- pixman_region32_fini(&gs->texture_damage);
- free(gs);
+ return 0;
}
static const char vertex_shader[] =
@@ -1432,50 +1520,24 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
}
static void
-output_apply_border(struct weston_output *output, struct gl_renderer *gr)
+gl_renderer_output_set_border(struct weston_output *output,
+ enum gl_renderer_border_side side,
+ int32_t width, int32_t height,
+ int32_t tex_width, unsigned char *data)
{
- output->border.top = gr->border.top;
- output->border.bottom = gr->border.bottom;
- output->border.left = gr->border.left;
- output->border.right = gr->border.right;
-}
-
-WL_EXPORT void
-gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
- int32_t *edges)
-{
- struct gl_renderer *gr = get_renderer(ec);
- struct weston_output *output;
-
- gr->border.left = edges[0];
- gr->border.right = edges[1];
- gr->border.top = edges[2];
- gr->border.bottom = edges[3];
-
- gr->border.width = width;
- gr->border.height = height;
-
- glGenTextures(1, &gr->border.texture);
- glBindTexture(GL_TEXTURE_2D, gr->border.texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
- width,
- height,
- 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
- data);
+ struct gl_output_state *go = get_output_state(output);
- wl_list_for_each(output, &ec->output_list, link)
- output_apply_border(output, gr);
+ go->borders[side].width = width;
+ go->borders[side].height = height;
+ go->borders[side].tex_width = tex_width;
+ go->borders[side].data = data;
+ go->borders[side].dirty = 1;
}
static int
gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
-WL_EXPORT int
+static int
gl_renderer_output_create(struct weston_output *output,
EGLNativeWindowType window)
{
@@ -1509,12 +1571,10 @@ gl_renderer_output_create(struct weston_output *output,
output->renderer_state = go;
- output_apply_border(output, gr);
-
return 0;
}
-WL_EXPORT void
+static void
gl_renderer_output_destroy(struct weston_output *output)
{
struct gl_renderer *gr = get_renderer(output->compositor);
@@ -1529,7 +1589,7 @@ gl_renderer_output_destroy(struct weston_output *output)
free(go);
}
-WL_EXPORT EGLSurface
+static EGLSurface
gl_renderer_output_surface(struct weston_output *output)
{
return get_output_state(output)->egl_surface;
@@ -1540,6 +1600,8 @@ gl_renderer_destroy(struct weston_compositor *ec)
{
struct gl_renderer *gr = get_renderer(ec);
+ wl_signal_emit(&gr->destroy_signal, gr);
+
if (gr->has_bind_display)
gr->unbind_display(gr->egl_display, ec->wl_display);
@@ -1552,9 +1614,11 @@ gl_renderer_destroy(struct weston_compositor *ec)
eglReleaseThread();
wl_array_release(&gr->vertices);
- wl_array_release(&gr->indices);
wl_array_release(&gr->vtxcnt);
+ weston_binding_destroy(gr->fragment_binding);
+ weston_binding_destroy(gr->fan_binding);
+
free(gr);
}
@@ -1602,7 +1666,7 @@ out:
return -1;
}
-WL_EXPORT const EGLint gl_renderer_opaque_attribs[] = {
+static const EGLint gl_renderer_opaque_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
@@ -1612,7 +1676,7 @@ WL_EXPORT const EGLint gl_renderer_opaque_attribs[] = {
EGL_NONE
};
-WL_EXPORT const EGLint gl_renderer_alpha_attribs[] = {
+static const EGLint gl_renderer_alpha_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
@@ -1622,7 +1686,7 @@ WL_EXPORT const EGLint gl_renderer_alpha_attribs[] = {
EGL_NONE
};
-WL_EXPORT int
+static int
gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
const EGLint *attribs, const EGLint *visual_id)
{
@@ -1638,9 +1702,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
gr->base.repaint_output = gl_renderer_repaint_output;
gr->base.flush_damage = gl_renderer_flush_damage;
gr->base.attach = gl_renderer_attach;
- gr->base.create_surface = gl_renderer_create_surface;
gr->base.surface_set_color = gl_renderer_surface_set_color;
- gr->base.destroy_surface = gl_renderer_destroy_surface;
gr->base.destroy = gl_renderer_destroy;
gr->egl_display = eglGetDisplay(display);
@@ -1665,6 +1727,8 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
+ wl_signal_init(&gr->destroy_signal);
+
return 0;
err_egl:
@@ -1673,7 +1737,7 @@ err_egl:
return -1;
}
-WL_EXPORT EGLDisplay
+static EGLDisplay
gl_renderer_display(struct weston_compositor *ec)
{
return get_renderer(ec)->egl_display;
@@ -1701,7 +1765,7 @@ compile_shaders(struct weston_compositor *ec)
gr->texture_shader_y_u_v.fragment_source =
texture_fragment_shader_y_u_v;
- gr->texture_shader_y_u_v.vertex_source = vertex_shader;
+ gr->texture_shader_y_xuxv.vertex_source = vertex_shader;
gr->texture_shader_y_xuxv.fragment_source =
texture_fragment_shader_y_xuxv;
@@ -1847,10 +1911,14 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
if (compile_shaders(ec))
return -1;
- weston_compositor_add_debug_binding(ec, KEY_S,
- fragment_debug_binding, ec);
- weston_compositor_add_debug_binding(ec, KEY_F,
- fan_debug_repaint_binding, ec);
+ gr->fragment_binding =
+ weston_compositor_add_debug_binding(ec, KEY_S,
+ fragment_debug_binding,
+ ec);
+ gr->fan_binding =
+ weston_compositor_add_debug_binding(ec, KEY_F,
+ fan_debug_repaint_binding,
+ ec);
weston_log("GL ES 2 renderer features:\n");
weston_log_continue(STAMP_SPACE "read-back format: %s\n",
@@ -1863,3 +1931,16 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
return 0;
}
+
+WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
+ .opaque_attribs = gl_renderer_opaque_attribs,
+ .alpha_attribs = gl_renderer_alpha_attribs,
+
+ .create = gl_renderer_create,
+ .display = gl_renderer_display,
+ .output_create = gl_renderer_output_create,
+ .output_destroy = gl_renderer_output_destroy,
+ .output_surface = gl_renderer_output_surface,
+ .output_set_border = gl_renderer_output_set_border,
+ .print_egl_error_state = gl_renderer_print_egl_error_state
+};