[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