[Mesa-dev] Problem with EGL_KHR_image_pixmap extension

gabriel muguerza glmcabra at gmail.com
Wed Mar 6 10:31:09 PST 2013


Hi,
I do not know if it's the right place for this, but I sent an email to the
Mesa-users mailing list explaining the problem, and I have no answers, so
if anyone can help, this is what happens:


I'm using Mesa 9.1, EGL and xcb, to make texture from pixmap.
Using EGL_KHR_image_pixmap,  i get errors in textures.
I have also checked texture_from_pixmap in the EGL demos, and the demo not
work.

I have no errors with Mesa 9.0,  my test code and demo work well.


Linux: archlinux
Mesa: mesa-9.1-2, (mesa-demos from git)
Drivers: intel-dri 9.1-2, xf86-video-intel 2.21.3-1
Kernel: 3.8.0-2-ARCH (same results with kernel 3.7.9)


I've re-checked the test-code with mesa 9.0, and the only error is that the
texture (texture_a) is upside down...



Test code:

// gcc -Wall -O3 egl-xcb-texture.c -o egl-xcb-texture  -lEGL -lGLESv1_CM
-lGLESv2 -lxcb -lxcb-util

#include <xcb/xcb.h>
#include <xcb/xcb_util.h>

#include <GLES/gl.h>
#include <GLES/glext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
//#include <GLES3/gl3.h>
//#include <GLES3/gl3ext.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>



float vert_tex_data[] = { 1.00f, 1.00f, 0.00f,        // Position 0
                          1.00f, 1.00f,               // TexCoord 0
                          -1.00f, 1.00f, 0.00f,        // Position 1
                          0.00f,  1.00f,                // TexCoord 1
                          -1.00f, -1.00f, 0.00f,       // Position 2
                          0.00f,  0.00f,               // TexCoord 2
                          1.00f, -1.00f, 0.00f,       // Position 3
                          1.00f,  0.00f};            // TexCoord 3

const GLushort index_data[] = {0, 1, 2,
                               2, 3, 0,};


struct ctx_t {
xcb_connection_t *conn;
int  num_scr;
xcb_screen_t *screen;
const xcb_setup_t *setup;
 xcb_generic_event_t *xcb_event;

xcb_window_t  window;
xcb_pixmap_t xpix;
GLuint                  texture_a;
GLuint                  texture_b;

EGLDisplay egl_dpy;
EGLConfig   egl_cfg;

EGLContext              egl_context;
        EGLSurface              egl_surface;
        GLuint                  shader_program;

        GLint                   loc_v_position;
        GLint                   loc_tex_coord;
        GLint                   loc_texture;

        PFNEGLCREATEIMAGEKHRPROC  eglCreateImageKHR;
    PFNEGLDESTROYIMAGEKHRPROC  eglDestroyImageKHR;
    PFNGLEGLIMAGETARGETTEXTURE2DOESPROC  glEGLImageTargetTexture2DOES;
};


void new_xwindow(struct ctx_t *ctx)
{
uint32_t values[5], mask;
xcb_colormap_t colormap = 0;
xcb_visualtype_t *visual = NULL;
xcb_visualid_t visual_id;
 visual = xcb_aux_find_visual_by_attrs(ctx->screen,
XCB_VISUAL_CLASS_TRUE_COLOR, 32);
visual_id = visual->visual_id;

colormap = xcb_generate_id(ctx->conn);
xcb_create_colormap(ctx->conn, XCB_COLORMAP_ALLOC_NONE, colormap,
ctx->screen->root, visual_id);

mask =  XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY |
XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
values[0] = 0;
values[1] = 0;
values[2] = XCB_GRAVITY_NORTH_WEST;
values[3] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
values[4] = colormap;
 ctx->window = xcb_generate_id(ctx->conn);
xcb_create_window(ctx->conn,
  32,
  ctx->window,
  ctx->screen->root,
  0,
  0,
  800,
  600,
  0, //border
  XCB_WINDOW_CLASS_INPUT_OUTPUT,
  visual_id,
  mask,
  values);
 xcb_free_colormap(ctx->conn, colormap);
xcb_flush(ctx->conn);
}

void make_pixmap(struct ctx_t *ctx, uint16_t w, uint16_t h, uint8_t depth)
{
xcb_gcontext_t gc = 0;
xcb_rectangle_t rec = {0, 0, w - 1, h - 1};
xcb_arc_t arc[] = {{0, 0, w - 1, h - 1, 0, 90 * 64}, {0, 0, w - 1, h - 1,
90 * 64, 90 * 64},
   {0, 0, w - 1, h - 1, 180 * 64, 90 * 64}, {0, 0, w - 1, h - 1, 270 * 64,
90 * 64}};
uint32_t red = 0xff0000, yellow = 0x808000, blue = 0x0000ff, green =
0x00ff00, violet = 0xff00ff;

ctx->xpix = xcb_generate_id(ctx->conn);
        xcb_create_pixmap(ctx->conn, depth, ctx->xpix, ctx->screen->root,
w, h);

        gc = xcb_generate_id(ctx->conn);
        xcb_create_gc(ctx->conn, gc, ctx->xpix, XCB_GC_FOREGROUND, &yellow);
        xcb_poly_fill_rectangle(ctx->conn, ctx->xpix, gc, 1, &rec);

        xcb_change_gc(ctx->conn, gc, XCB_GC_FOREGROUND, &blue);
        xcb_poly_rectangle(ctx->conn, ctx->xpix, gc, 1, &rec);

        xcb_change_gc(ctx->conn, gc, XCB_GC_FOREGROUND, &red);
        xcb_poly_fill_arc(ctx->conn, ctx->xpix, gc, 1, &arc[0]);

        xcb_change_gc(ctx->conn, gc, XCB_GC_FOREGROUND, &blue);
        xcb_poly_fill_arc(ctx->conn, ctx->xpix, gc, 1, &arc[1]);

        xcb_change_gc(ctx->conn, gc, XCB_GC_FOREGROUND, &green);
        xcb_poly_fill_arc(ctx->conn, ctx->xpix, gc, 1, &arc[2]);

        xcb_change_gc(ctx->conn, gc, XCB_GC_FOREGROUND, &violet);
        xcb_poly_fill_arc(ctx->conn, ctx->xpix, gc, 1, &arc[3]);

        xcb_copy_area(ctx->conn, ctx->xpix, ctx->window, gc, 0, 0, 0, 0, w,
h);
        xcb_free_gc(ctx->conn, gc);
}

void mirror(uint8_t *src, int len, int stride, uint8_t *dst)
{
uint8_t *out = dst + len - stride;
uint8_t *in = NULL;

for (in = src; in < src + len; in += stride) {
memcpy(out, in, stride);
out -= stride;
}
}


//Esta textura anda ok.
//texture ok
int make_texture_b(struct ctx_t *ctx)
{
xcb_get_geometry_cookie_t g_cookie;
xcb_get_geometry_reply_t *g_reply = NULL;
uint16_t w, h;
xcb_get_image_cookie_t cookie;
xcb_get_image_reply_t *reply =NULL;
uint8_t *pixels = NULL;
uint8_t *buffer = NULL;
int len, stride;
 g_cookie = xcb_get_geometry(ctx->conn, ctx->xpix);
g_reply = xcb_get_geometry_reply(ctx->conn, g_cookie, NULL);
if (!g_reply) return -1;

w = g_reply->width;
h = g_reply->height;
free(g_reply);

cookie = xcb_get_image(ctx->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, ctx->xpix, 0,
0, w, h, 0xffffffff);
reply = xcb_get_image_reply(ctx->conn, cookie, NULL);
if (!reply) return -1;

pixels = xcb_get_image_data(reply);
len = xcb_get_image_data_length(reply);

stride = w * 4;
buffer = malloc(len);
mirror(pixels, len, stride, buffer);
free(reply);

glGenTextures(1, &ctx->texture_b);
        glBindTexture(GL_TEXTURE_2D, ctx->texture_b);

        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_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D,
                     0,
                     GL_BGRA_EXT,
                     w,
                     h,
                     0,
                     GL_BGRA_EXT,
                     GL_UNSIGNED_BYTE,
                     buffer);

        free(buffer);
        return 0;
}


//Esta textura anda mal.
//texture bad
void make_texture_a(struct ctx_t *ctx)
{
EGLImageKHR khrimg = NULL;
const EGLint attr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
//EGL_GL_TEXTURE_LEVEL_KHR, 0, // mip map level to reference
EGL_NONE};

khrimg = ctx->eglCreateImageKHR(ctx->egl_dpy,
                                EGL_NO_CONTEXT,
                                EGL_NATIVE_PIXMAP_KHR,
                                (EGLClientBuffer)(uintptr_t)ctx->xpix,
                                attr);

glGenTextures(1, &ctx->texture_a);
        glBindTexture(GL_TEXTURE_2D, ctx->texture_a);

        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_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        ctx->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
(GLeglImageOES)khrimg);
        ctx->eglDestroyImageKHR(ctx->egl_dpy, khrimg);
}

void init_xcb(struct ctx_t *ctx)
{
ctx->conn = xcb_connect(NULL, &ctx->num_scr);
ctx->screen = xcb_aux_get_screen(ctx->conn, ctx->num_scr);
ctx->setup = xcb_get_setup(ctx->conn);
xcb_flush(ctx->conn);
}

void init_egl(struct ctx_t *ctx)
{
EGLint attr[] = {EGL_BUFFER_SIZE, 32,
        EGL_RED_SIZE, 8,
          EGL_GREEN_SIZE, 8,
          EGL_BLUE_SIZE, 8,
          EGL_ALPHA_SIZE, 8,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT | EGL_OPENGL_BIT,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT,
        EGL_MATCH_NATIVE_PIXMAP, (GLint)ctx->screen->root,
        EGL_NONE};

   //ctx->egl_dpy  =  eglGetDisplay((EGLNativeDisplayType)NULL);
   ctx->egl_dpy  =  eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(ctx->egl_dpy, NULL, NULL);

    EGLint     num_config;
    eglChooseConfig(ctx->egl_dpy, attr, &ctx->egl_cfg, 1, &num_config);

    ctx->egl_surface = eglCreateWindowSurface(ctx->egl_dpy, ctx->egl_cfg,
ctx->window, NULL);
        ctx->egl_context = eglCreateContext(ctx->egl_dpy,
                                            ctx->egl_cfg,
                                            EGL_NO_CONTEXT,

(EGLint[]){EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE});

        eglMakeCurrent(ctx->egl_dpy, ctx->egl_surface, ctx->egl_surface,
ctx->egl_context);

        eglBindAPI(EGL_OPENGL_ES_API);

        ctx->eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)
eglGetProcAddress("eglCreateImageKHR");
ctx->eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)
eglGetProcAddress("eglDestroyImageKHR");
ctx->glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
eglGetProcAddress("glEGLImageTargetTexture2DOES");
}

void init_shaders(struct ctx_t *ctx)
{
const char *vertx_src = " \
attribute vec4 v_position;   \
attribute vec2 tex_coord;  \
varying mediump vec2 v_tex_coord; \
    \
void main()                           \
{                                     \
gl_Position = v_position;   \
       v_tex_coord = tex_coord;  \
}";

const char *frag_src = " \
varying mediump vec2 v_tex_coord;   \
uniform sampler2D texture; \
  \
void  main() \
{ \
gl_FragColor = texture2D(texture, v_tex_coord); \
}";

GLuint vertex_shader, fragment_shader;

ctx->shader_program = glCreateProgram();

    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
     glShaderSource(vertex_shader, 1, &vertx_src, NULL);
    glCompileShader(vertex_shader);

    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
     glShaderSource(fragment_shader, 1, &frag_src, NULL);
    glCompileShader(fragment_shader);
 glAttachShader(ctx->shader_program, vertex_shader);
    glAttachShader(ctx->shader_program, fragment_shader);

    glLinkProgram(ctx->shader_program);

    glDetachShader(ctx->shader_program, vertex_shader);
glDetachShader(ctx->shader_program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
}


void  render(struct ctx_t *ctx)
{
glClear(GL_COLOR_BUFFER_BIT);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, index_data);
        eglSwapBuffers(ctx->egl_dpy, ctx->egl_surface);
}


int main()
{
struct ctx_t ctx;

init_xcb(&ctx);
new_xwindow(&ctx);
xcb_map_window(ctx.conn, ctx.window);
xcb_flush(ctx.conn);

make_pixmap(&ctx, 400, 200, 32);
xcb_flush(ctx.conn);
 init_egl(&ctx);
make_texture_a(&ctx);
make_texture_b(&ctx);

init_shaders(&ctx);

glUseProgram(ctx.shader_program);
ctx.loc_v_position = glGetAttribLocation(ctx.shader_program, "v_position");
        ctx.loc_texture = glGetUniformLocation(ctx.shader_program,
"texture");
        ctx.loc_tex_coord = glGetAttribLocation(ctx.shader_program,
"tex_coord");

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, ctx.texture_a);
        // Set the sampler texture unit to 0
        glUniform1i(ctx.loc_texture, 0);

        glEnableVertexAttribArray(ctx.loc_v_position);
        glVertexAttribPointer(ctx.loc_v_position, 3, GL_FLOAT, GL_FALSE, 5
* sizeof(GLfloat), vert_tex_data);
        // set the texture coords
        glEnableVertexAttribArray(ctx.loc_tex_coord);
        glVertexAttribPointer(ctx.loc_tex_coord, 2, GL_FLOAT, GL_FALSE, 5 *
sizeof(GLfloat), &vert_tex_data[3]);

        glViewport(0, 0, 800, 600);

        xcb_flush(ctx.conn);
for (;;) {
ctx.xcb_event = xcb_wait_for_event(ctx.conn);
if (xcb_connection_has_error(ctx.conn)) goto out;
 uint8_t ev_type;
ev_type = ctx.xcb_event->response_type & ~0x80;
if (ev_type == XCB_KEY_PRESS) {
xcb_key_press_event_t *ev = (xcb_key_press_event_t *)ctx.xcb_event;
if (ev->detail == 9) { //Esc
goto out;
}

                        //key a ---> show bad texture
if (ev->detail == 38) { //key a
glBindTexture(GL_TEXTURE_2D, ctx.texture_a);
render(&ctx);
}

                        //key b ---> show texture ok
if (ev->detail == 56) { //key b
glBindTexture(GL_TEXTURE_2D, ctx.texture_b);
render(&ctx);
}
}

free(ctx.xcb_event);
ctx.xcb_event = NULL;
xcb_flush(ctx.conn);
}
out:
glDisableVertexAttribArray(ctx.loc_v_position);
        glDisableVertexAttribArray(ctx.loc_tex_coord);
        glDeleteTextures(1, &ctx.texture_a);
        glDeleteTextures(1, &ctx.texture_b);
glDeleteProgram(ctx.shader_program);
        eglDestroySurface(ctx.egl_dpy, ctx.egl_surface);
        eglMakeCurrent(ctx.egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
    eglDestroyContext(ctx.egl_dpy, ctx.egl_context);
    eglTerminate(ctx.egl_dpy);
    eglReleaseThread();

    if (ctx.xcb_event) free(ctx.xcb_event);

    xcb_free_pixmap(ctx.conn, ctx.xpix);
    xcb_destroy_window(ctx.conn, ctx.window);
    xcb_disconnect(ctx.conn);
    return 0;
}



original pixmap:
http://www.freeimagehosting.net/33j4c

texture ok:
http://www.freeimagehosting.net/dzh2d

texture bad:
http://www.freeimagehosting.net/pnd7r


I appreciate any help, thanks.
Gabriel.
(Sorry for my English, not my native language)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20130306/1c2eaea2/attachment-0001.html>


More information about the mesa-dev mailing list