Page 1 of 1

Getting eglCopyBuffers working

Posted: Mon Jun 04, 2012 1:29 pm
by theHetman
So first a little background:

I'm trying to get OpenGL ES 2.0 and OpenVG to render in a window under X. So far I've managed to get GLES to render to an EGL pixmap using eglCreateGlobalImageBRCM and then binding it to an EGL surface. I can grab pixels back from the output buffer using glReadPixels and from that I can see that I can correctly create surface types of ARGB_8888 (I see full colour data and alpha using glReadPixels), XRGB_8888 (the alpha is alway 0xff) and RGB_565 (I see colour artifacts as the data is truncated and then padded back out to 8 bits per channel). The problem is that glReadPixels only supports GL_RGBA and GL_RGB as output formats and so writing to a 565 X Window is a slow bit mangling operation using the CPU. teh_orph showed the way with this.

There seem to be very few ways to get data from GPU land into CPU land but one way that I've been trying is creating a pixmap using XCreatePixmap with the width, height and colour depth of the X Window and then using eglCopyBuffers to copy the EGL surface to the pixmap. Then I finally use XCopyArea to copy the pixmap to the window.

The trouble is that eglCopyBuffers fails with an EGL_BAD_MATCH error and nothing I try seems to fix this. Does anyone have any ideas?

Re: Getting eglCopyBuffers working

Posted: Tue Jun 05, 2012 4:14 pm
by dom
I can confirm the function is present. The obvious reason for EGL_BAD_MATCH is:
if (image.width != surface->width || image.height != surface->height) {
thread->error = EGL_BAD_MATCH;

Re: Getting eglCopyBuffers working

Posted: Tue Jun 05, 2012 4:48 pm
by theHetman
Hmmmm, I've been really careful that the width, height and bit depth are all the same heres that code that creates the X window and pixmap:

Code: Select all

	gXDisplay = XOpenDisplay(NULL);
	if (gXDisplay)
	{
		printf("X found\n");
		gContext.flags |= PI_DISPLAY_XWINDOWS;
		x_attrib.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
		gWindow = XCreateWindow(gXDisplay, DefaultRootWindow(gXDisplay), 0, 0, width, height, 0, CopyFromParent,
						InputOutput, CopyFromParent, CWEventMask, &x_attrib);
		XMapWindow(gXDisplay, gWindow);
		XStoreName(gXDisplay, gWindow, windowName);
		gGC = DefaultGC(gXDisplay, 0);
		XGetWindowAttributes(gXDisplay, gWindow, &wa);
		gPixmap = XCreatePixmap(gXDisplay, gWindow, wa.width, wa.height, wa.depth);
		
		printf("attr = %i, %i, %i\n", wa.width, wa.height, wa.depth);
		gContext.width = width;
		gContext.height = height;
		
	} 
and here's the code that creates the surface:

Code: Select all

		pixmap[0] = 0;
		pixmap[1] = 0;
		pixmap[2] = width;
		pixmap[3] = height;
		eglGetConfigAttrib(gEGLDisplay, config, EGL_RED_SIZE, &val);
		pixmap[4] = EGL_PIXEL_FORMAT_RGB_565_BRCM;
		stride = width << 1;
		if (val == 8)
		{
			pixmap[4] = EGL_PIXEL_FORMAT_XRGB_8888_BRCM;
			stride <<= 1;
		}
		eglGetConfigAttrib(gEGLDisplay, config, EGL_ALPHA_SIZE, &val);
		if (val == 8)
		{
			pixmap[4] = EGL_PIXEL_FORMAT_ARGB_8888_BRCM;
		}
		eglGetConfigAttrib(gEGLDisplay, config, EGL_RENDERABLE_TYPE, &val);
		if (val & EGL_OPENGL_ES_BIT)
		{
			pixmap[4] |= EGL_PIXEL_FORMAT_RENDER_GLES_BRCM | EGL_PIXEL_FORMAT_GLES_TEXTURE_BRCM;
		}
		if (val & EGL_OPENGL_ES2_BIT)
		{
			pixmap[4] |= EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM | EGL_PIXEL_FORMAT_GLES2_TEXTURE_BRCM;
		}
		if (val & EGL_OPENVG_BIT)
		{
			pixmap[4] |= EGL_PIXEL_FORMAT_RENDER_VG_BRCM | EGL_PIXEL_FORMAT_VG_IMAGE_BRCM;
		}
		if (val & EGL_OPENGL_BIT)
		{
			pixmap[4] |= EGL_PIXEL_FORMAT_RENDER_GL_BRCM;
		}
		eglCreateGlobalImageBRCM(width, height, pixmap[4], 0, stride, pixmap);
		printf("id = %i, %i, %i, %i, %x\n", pixmap[0], pixmap[1], pixmap[2], pixmap[3], pixmap[4]);
		gEGLSurface = eglCreatePixmapSurface(gEGLDisplay, config, pixmap, NULL);
		gImageID = pixmap[0];
		if (gEGLSurface == EGL_NO_SURFACE)
		{
			printf("Failed to create EGL surface\n");
			return NULL;
		}
and finally the code at the end of the render loop:

Code: Select all

			if (eglCopyBuffers(gEGLDisplay, gEGLSurface, &gPixmap) == EGL_FALSE)
			{
				if (!temp_flag)
				{
					EGLint e = eglGetError();
					printf("copyBuffers failed: %i (0x%.8x)\n", e, e);
				}
			}
			XCopyArea(gXDisplay,  gPixmap, gWindow, gGC, 0, 0, gContext.width, gContext.height, 0, 0);
As you can see there are some printfs in the code and the output looks like this:

Code: Select all

X found
attr = 640, 480, 16
id = 1, 0, 640, 480, 3f1
copyBuffers failed: 12297 (0x00003009)
So I'm not sure what's going on.