This patch ignores the borders for now.

Signed-off-by: Niels Ole Salscheider <niels_...@salscheider-online.de>
---
 src/gl-renderer.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 226 insertions(+), 8 deletions(-)

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 470f98a..4bc8b9b 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -38,6 +38,8 @@
 #include <EGL/eglext.h>
 #include "weston-egl-ext.h"
 
+#include "cms-server-protocol.h"
+
 struct gl_shader {
        GLuint program;
        GLuint vertex_shader, fragment_shader;
@@ -74,6 +76,10 @@ struct gl_output_state {
        enum gl_border_status border_damage[BUFFER_DAMAGE_COUNT];
        struct gl_border_image borders[4];
        enum gl_border_status border_status;
+
+       GLuint fb;
+       GLuint fb_texture;
+       GLuint lut;
 };
 
 enum buffer_type {
@@ -85,6 +91,7 @@ enum buffer_type {
 struct gl_surface_state {
        GLfloat color[4];
        struct gl_shader *shader;
+       struct gl_shader *lut_shader;
 
        GLuint textures[3];
        int num_textures;
@@ -97,6 +104,8 @@ struct gl_surface_state {
        GLenum gl_format;
        GLenum gl_pixel_type;
 
+       GLuint lut;
+
        EGLImageKHR images[3];
        GLenum target;
        int num_images;
@@ -531,6 +540,67 @@ shader_uniforms(struct gl_shader *shader,
 }
 
 static void
+gl_renderer_attach_lut(struct weston_surface *es)
+{
+       struct weston_compositor *ec = es->compositor;
+       struct gl_renderer *gr = get_renderer(ec);
+       struct gl_surface_state *gs = get_surface_state(es);
+
+       if (!gs->lut) {
+               glGenTextures(1, &gs->lut);
+               glBindTexture(GL_TEXTURE_3D_OES, gs->lut);
+               glTexParameteri(GL_TEXTURE_3D_OES,
+                               GL_TEXTURE_WRAP_R_OES, GL_CLAMP_TO_EDGE);
+               glTexParameteri(GL_TEXTURE_3D_OES,
+                               GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+               glTexParameteri(GL_TEXTURE_3D_OES,
+                               GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       } else
+               glBindTexture(GL_TEXTURE_3D_OES, gs->lut);
+
+#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
+       gr->teximage3d(GL_TEXTURE_3D_OES, 0, GL_RGB,
+                      es->colorspace->clut.points, es->colorspace->clut.points,
+                      es->colorspace->clut.points, 0, GL_RGB, GL_UNSIGNED_BYTE,
+                      es->colorspace->clut.data);
+}
+
+static void
+gl_renderer_attach_output_lut(struct weston_output *output)
+{
+       struct gl_renderer *gr = get_renderer(output->compositor);
+       struct gl_output_state *go = get_output_state(output);
+
+       if (!go->lut) {
+               glGenTextures(1, &go->lut);
+               glBindTexture(GL_TEXTURE_3D_OES, go->lut);
+               glTexParameteri(GL_TEXTURE_3D_OES,
+                               GL_TEXTURE_WRAP_R_OES, GL_CLAMP_TO_EDGE);
+               glTexParameteri(GL_TEXTURE_3D_OES,
+                               GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+               glTexParameteri(GL_TEXTURE_3D_OES,
+                               GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       } else
+               glBindTexture(GL_TEXTURE_3D_OES, go->lut);
+
+#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
+       gr->teximage3d(GL_TEXTURE_3D_OES, 0, GL_RGB,
+                      output->colorspace->clut.points,
+                      output->colorspace->clut.points,
+                      output->colorspace->clut.points,
+                      0, GL_RGB, GL_UNSIGNED_BYTE,
+                      output->colorspace->clut.data);
+}
+
+static void
 draw_view(struct weston_view *ev, struct weston_output *output,
          pixman_region32_t *damage) /* in global coordinates */
 {
@@ -547,7 +617,7 @@ draw_view(struct weston_view *ev, struct weston_output 
*output,
        /* 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)
+       if (!gs->shader || !gs->lut_shader)
                return;
 
        pixman_region32_init(&repaint);
@@ -565,8 +635,14 @@ draw_view(struct weston_view *ev, struct weston_output 
*output,
                shader_uniforms(&gr->solid_shader, ev, output);
        }
 
-       use_shader(gr, gs->shader);
-       shader_uniforms(gs->shader, ev, output);
+       if (gr->has_texture_3d && ev->surface->colorspace->clut.data) {
+               use_shader(gr, gs->lut_shader);
+               shader_uniforms(gs->lut_shader, ev, output);
+       } else {
+               use_shader(gr, gs->shader);
+               shader_uniforms(gs->shader, ev, output);
+       }
+
 
        if (ev->transform.enabled || output->zoom.active ||
            output->current_scale != ev->surface->buffer_viewport.buffer.scale)
@@ -581,6 +657,17 @@ draw_view(struct weston_view *ev, struct weston_output 
*output,
                glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
        }
 
+       /* Set LUT */
+       if (gr->has_texture_3d && ev->surface->colorspace->clut.data) {
+               gl_renderer_attach_lut(ev->surface);
+               glActiveTexture(GL_TEXTURE0 + i);
+               glBindTexture(GL_TEXTURE_3D_OES, gs->lut);
+               glTexParameteri(GL_TEXTURE_3D_OES, GL_TEXTURE_MIN_FILTER,
+                               GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_3D_OES, GL_TEXTURE_MAG_FILTER,
+                               GL_LINEAR);
+       }
+
        /* blended region is whole surface minus opaque region: */
        pixman_region32_init_rect(&surface_blend, 0, 0,
                                  ev->surface->width, ev->surface->height);
@@ -588,14 +675,23 @@ draw_view(struct weston_view *ev, struct weston_output 
*output,
 
        /* XXX: Should we be using ev->transform.opaque here? */
        if (pixman_region32_not_empty(&ev->surface->opaque)) {
-               if (gs->shader == &gr->texture_shader_rgba) {
+               if (gs->shader == &gr->texture_shader_rgba ||
+                   gs->lut_shader == &gr->texture_shader_rgba_lut) {
                        /* Special case for RGBA textures with possibly
                         * bad data in alpha channel: use the shader
                         * that forces texture alpha = 1.0.
                         * Xwayland surfaces need this.
                         */
-                       use_shader(gr, &gr->texture_shader_rgbx);
-                       shader_uniforms(&gr->texture_shader_rgbx, ev, output);
+                       if (gr->has_texture_3d &&
+                           ev->surface->colorspace->clut.data) {
+                               use_shader(gr, &gr->texture_shader_rgbx_lut);
+                               shader_uniforms(&gr->texture_shader_rgbx_lut,
+                                               ev, output);
+                       } else {
+                               use_shader(gr, &gr->texture_shader_rgbx);
+                               shader_uniforms(&gr->texture_shader_rgbx,
+                                               ev, output);
+                       }
                }
 
                if (ev->alpha < 1.0)
@@ -607,7 +703,13 @@ draw_view(struct weston_view *ev, struct weston_output 
*output,
        }
 
        if (pixman_region32_not_empty(&surface_blend)) {
-               use_shader(gr, gs->shader);
+               if (gr->has_texture_3d && ev->surface->colorspace->clut.data) {
+                       use_shader(gr, gs->lut_shader);
+                       shader_uniforms(gs->lut_shader, ev, output);
+               } else {
+                       use_shader(gr, gs->shader);
+                       shader_uniforms(gs->shader, ev, output);
+               }
                glEnable(GL_BLEND);
                repaint_region(ev, &repaint, &surface_blend);
        }
@@ -864,6 +966,95 @@ output_rotate_damage(struct weston_output *output,
 }
 
 static void
+use_fb(struct weston_output *output, GLuint *texture)
+{
+       struct gl_output_state *go = get_output_state(output);
+
+       if (!go->fb)
+               glGenFramebuffers(1, &go->fb);
+       glBindFramebuffer(GL_FRAMEBUFFER, go->fb);
+
+       if (!*texture)
+               glGenTextures(1, texture);
+       glBindTexture(GL_TEXTURE_2D, *texture);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, output->width,
+                    output->height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+                       GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+                       GL_NEAREST);
+
+       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                              GL_TEXTURE_2D, *texture, 0);
+}
+
+static int
+draw_fb(struct weston_output *output)
+{
+       struct gl_output_state *go = get_output_state(output);
+       struct weston_compositor *compositor = output->compositor;
+       struct gl_renderer *gr = get_renderer(compositor);
+
+       static GLushort indices [] = { 0, 1, 3, 2 };
+
+       GLfloat texcoord[] = {
+               0.0f, 0.0f,
+               1.0f, 0.0f,
+               1.0f, 1.0f,
+               0.0f, 1.0f,
+       };
+
+       GLfloat verts[] = {
+               output->x,                 output->y,
+               output->x + output->width, output->y,
+               output->x + output->width, output->y + output->height,
+               output->x,                 output->y + output->height
+       };
+
+       struct weston_matrix matrix;
+
+       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+       use_shader(gr, &gr->fb_shader);
+
+       glViewport(0, 0, output->width, output->height);
+
+       weston_matrix_init(&matrix);
+       weston_matrix_translate(&matrix,
+                               -(output->x + output->width / 2.0),
+                               -(output->y + output->height / 2.0), 0);
+       weston_matrix_scale(&matrix,
+                           2.0 / output->width,
+                           2.0 / output->height, 1);
+       glUniformMatrix4fv(gr->fb_shader.proj_uniform, 1, GL_FALSE, matrix.d);
+
+       glUniform1i(gr->fb_shader.tex_uniforms[0], 0);
+       glUniform1i(gr->fb_shader.lut_uniform, 1);
+
+       glActiveTexture(GL_TEXTURE0);
+       glBindTexture(GL_TEXTURE_2D, go->fb_texture);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+       glActiveTexture(GL_TEXTURE1);
+       glBindTexture(GL_TEXTURE_3D_OES, go->lut);
+       glTexParameteri(GL_TEXTURE_3D_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_3D_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+       glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
+       glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
+       glEnableVertexAttribArray(0);
+       glEnableVertexAttribArray(1);
+
+       glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices);
+
+       glDisableVertexAttribArray(1);
+       glDisableVertexAttribArray(0);
+
+       return 0;
+}
+
+static void
 gl_renderer_repaint_output(struct weston_output *output,
                              pixman_region32_t *output_damage)
 {
@@ -889,6 +1080,9 @@ gl_renderer_repaint_output(struct weston_output *output,
        if (use_output(output) < 0)
                return;
 
+       if (gr->has_texture_3d && output->colorspace->clut.data)
+               use_fb(output, &go->fb_texture);
+
        /* if debugging, redraw everything outside the damage to clean up
         * debug lines from the previous draw on this buffer:
         */
@@ -918,8 +1112,14 @@ gl_renderer_repaint_output(struct weston_output *output,
        pixman_region32_fini(&buffer_damage);
 
        draw_output_borders(output, border_damage);
-
        pixman_region32_copy(&output->previous_damage, output_damage);
+
+       if (gr->has_texture_3d && output->colorspace->clut.data) {
+               gl_renderer_attach_output_lut(output);
+               if (draw_fb(output) < 0)
+                       return;
+       }
+
        wl_signal_emit(&output->frame_signal, output);
 
 #ifdef EGL_EXT_swap_buffers_with_damage
@@ -1134,18 +1334,21 @@ gl_renderer_attach_shm(struct weston_surface *es, 
struct weston_buffer *buffer,
 
        switch (wl_shm_buffer_get_format(shm_buffer)) {
        case WL_SHM_FORMAT_XRGB8888:
+               gs->lut_shader = &gr->texture_shader_rgbx_lut;
                gs->shader = &gr->texture_shader_rgbx;
                pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
                gl_format = GL_BGRA_EXT;
                gl_pixel_type = GL_UNSIGNED_BYTE;
                break;
        case WL_SHM_FORMAT_ARGB8888:
+               gs->lut_shader = &gr->texture_shader_rgba_lut;
                gs->shader = &gr->texture_shader_rgba;
                pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
                gl_format = GL_BGRA_EXT;
                gl_pixel_type = GL_UNSIGNED_BYTE;
                break;
        case WL_SHM_FORMAT_RGB565:
+               gs->lut_shader = &gr->texture_shader_rgbx_lut;
                gs->shader = &gr->texture_shader_rgbx;
                pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
                gl_format = GL_RGB;
@@ -1207,23 +1410,28 @@ gl_renderer_attach_egl(struct weston_surface *es, 
struct weston_buffer *buffer,
        case EGL_TEXTURE_RGBA:
        default:
                num_planes = 1;
+               gs->lut_shader = &gr->texture_shader_rgba_lut;
                gs->shader = &gr->texture_shader_rgba;
                break;
        case EGL_TEXTURE_EXTERNAL_WL:
                num_planes = 1;
                gs->target = GL_TEXTURE_EXTERNAL_OES;
+               gs->lut_shader = &gr->texture_shader_egl_external_lut;
                gs->shader = &gr->texture_shader_egl_external;
                break;
        case EGL_TEXTURE_Y_UV_WL:
                num_planes = 2;
+               gs->lut_shader = &gr->texture_shader_y_uv; /* TODO */
                gs->shader = &gr->texture_shader_y_uv;
                break;
        case EGL_TEXTURE_Y_U_V_WL:
                num_planes = 3;
+               gs->lut_shader = &gr->texture_shader_y_u_v; /* TODO */
                gs->shader = &gr->texture_shader_y_u_v;
                break;
        case EGL_TEXTURE_Y_XUXV_WL:
                num_planes = 2;
+               gs->lut_shader = &gr->texture_shader_y_xuxv; /* TODO */
                gs->shader = &gr->texture_shader_y_xuxv;
                break;
        }
@@ -1276,6 +1484,8 @@ gl_renderer_attach(struct weston_surface *es, struct 
weston_buffer *buffer)
                gs->num_images = 0;
                glDeleteTextures(gs->num_textures, gs->textures);
                gs->num_textures = 0;
+               if (gs->lut)
+                       glDeleteTextures(1, &gs->lut);
                gs->buffer_type = BUFFER_TYPE_NULL;
                gs->y_inverted = 1;
                return;
@@ -1308,6 +1518,7 @@ gl_renderer_surface_set_color(struct weston_surface 
*surface,
        gs->color[2] = blue;
        gs->color[3] = alpha;
 
+       gs->lut_shader = &gr->solid_shader; /* TODO */
        gs->shader = &gr->solid_shader;
 }
 
@@ -1322,6 +1533,8 @@ surface_state_destroy(struct gl_surface_state *gs, struct 
gl_renderer *gr)
        gs->surface->renderer_state = NULL;
 
        glDeleteTextures(gs->num_textures, gs->textures);
+       if (gs->lut)
+               glDeleteTextures(1, &gs->lut);
 
        for (i = 0; i < gs->num_images; i++)
                gr->destroy_image(gr->egl_display, gs->images[i]);
@@ -1874,6 +2087,11 @@ gl_renderer_output_destroy(struct weston_output *output)
        for (i = 0; i < 2; i++)
                pixman_region32_fini(&go->buffer_damage[i]);
 
+       if (go->fb_texture)
+               glDeleteTextures(1, &go->fb_texture);
+       if (go->fb)
+               glDeleteFramebuffers(1, &go->fb);
+
        eglDestroySurface(gr->egl_display, go->egl_surface);
 
        free(go);
-- 
2.1.2

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to