Problem with EGL_KHR_image_pixmap extension

gabriel muguerza <[email protected]>
Newsgroups gmane.comp.video.mesa3d.user
Message-ID <CAJvabWAriOV0X_ZM6ZY00WjOg8jC4farjCUVduVbHuSYMojM4A@mail.gmail.com>
Hi,
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.


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;
 }
}

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;
}

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;
}
 if (ev->detail == 38) { //key a
glBindTexture(GL_TEXTURE_2D, ctx.texture_a);
render(&ctx);
 }
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


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 appreciate any help, thanks.

(Sorry for my English, not my native language)
Gabriel.

_______________________________________________
mesa-users mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-users
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.