--- a/m3g/m3gcore11/src/m3g_rendercontext.inl Tue Feb 02 01:47:50 2010 +0200
+++ b/m3g/m3gcore11/src/m3g_rendercontext.inl Fri Apr 16 16:21:04 2010 +0300
@@ -26,7 +26,7 @@
# error This file is for the OES API only
#endif
-#include <GLES/egl.h>
+#include <EGL/egl.h>
#include "m3g_image.h"
/*----------------------------------------------------------------------
@@ -40,9 +40,10 @@
*/
static EGLConfig m3gQueryEGLConfig(M3Genum format,
M3Gbitmask bufferBits,
- EGLint surfaceBits)
+ EGLint surfaceBits,
+ M3GNativeBitmap bitmapHandle)
{
- struct { int attrib, value; } attribs[9];
+ struct { int attrib, value; } attribs[10];
int samples;
/* Determine color depth */
@@ -93,37 +94,72 @@
attribs[5].attrib = EGL_SURFACE_TYPE;
attribs[5].value = surfaceBits;
- /* Try to get multisampling if requested */
+
+ if (bitmapHandle) {
+ /* This attribute is matched only for pixmap targets */
+ attribs[6].attrib = EGL_MATCH_NATIVE_PIXMAP;
+ attribs[6].value = bitmapHandle;
+
+ /* Try to get multisampling if requested */
+
+ attribs[7].attrib = EGL_SAMPLE_BUFFERS;
+ attribs[8].attrib = EGL_SAMPLES;
- attribs[6].attrib = EGL_SAMPLE_BUFFERS;
- attribs[7].attrib = EGL_SAMPLES;
- attribs[8].attrib = EGL_NONE;
+ attribs[9].attrib = EGL_NONE;
+ } else {
+ /* Try to get multisampling if requested */
+ attribs[6].attrib = EGL_SAMPLE_BUFFERS;
+ attribs[7].attrib = EGL_SAMPLES;
+
+ attribs[8].attrib = EGL_NONE;
+ }
+
+
/* Try 4 samples if multisampling enabled, then 2, then 1 */
samples = (bufferBits & M3G_MULTISAMPLE_BUFFER_BIT) ? 4 : 1;
for ( ; samples > 0; samples >>= 1) {
- if (samples > 1) {
- attribs[6].value = 1;
- attribs[7].value = samples;
- }
- else {
- attribs[6].value = EGL_FALSE;
- attribs[7].value = 0;
+ if (bitmapHandle) {
+ if (samples > 1) {
+ attribs[7].value = 1;
+ attribs[8].value = samples;
+ }
+ else {
+ attribs[7].value = EGL_FALSE;
+ attribs[8].value = 0;
+ }
+ } else {
+ if (samples > 1) {
+ attribs[6].value = 1;
+ attribs[7].value = samples;
+ }
+ else {
+ attribs[6].value = EGL_FALSE;
+ attribs[7].value = 0;
+ }
}
/* Get the first matching config; according to EGL sorting
* rules, this should be an accelerated one if possible */
{
EGLConfig config;
- int numConfigs;
+ int numConfigs;
+ EGLint error;
+
eglChooseConfig(eglGetDisplay(EGL_DEFAULT_DISPLAY),
(const int *) attribs,
&config, 1,
&numConfigs);
- M3G_ASSERT(eglGetError() == EGL_SUCCESS);
+ error = eglGetError();
+ if (error != EGL_SUCCESS) {
+ M3G_LOG1(M3G_LOG_FATAL_ERRORS, "eglChooseConfig failed: %d\n", error);
+ }
+
+
+ M3G_ASSERT(error == EGL_SUCCESS);
/* If we got a config, return that; otherwise, drop the
* number of multisampling samples and try again, or
@@ -154,6 +190,7 @@
{
M3G_LOG(M3G_LOG_INTERFACE, "Initializing EGL\n");
eglInitialize(eglGetDisplay(EGL_DEFAULT_DISPLAY), NULL, NULL);
+ eglBindAPI(EGL_OPENGL_ES_API);
}
/*!
@@ -170,7 +207,7 @@
* \internal
* \brief Creates a new EGL context
*/
-static EGLContext m3gCreateGLContext(M3Genum format,
+/*static EGLContext m3gCreateGLContext(M3Genum format,
M3Gbitmask bufferBits,
M3Gbitmask reqSurfaceBits,
EGLContext share,
@@ -181,7 +218,7 @@
M3G_ASSERT((reqSurfaceBits & ~(EGL_PIXMAP_BIT|EGL_PBUFFER_BIT|EGL_WINDOW_BIT)) == 0);
- config = m3gQueryEGLConfig(format, bufferBits, reqSurfaceBits);
+ config = m3gQueryEGLConfig(format, bufferBits, reqSurfaceBits, NULL);
if (!config || !eglGetConfigAttrib(eglGetDisplay(EGL_DEFAULT_DISPLAY),
config,
@@ -205,7 +242,7 @@
M3G_LOG1(M3G_LOG_OBJECTS, "New GL context 0x%08X\n", (unsigned) ctx);
return ctx;
}
-
+*/
/*!
* \internal
* \brief Deletes an EGL context
@@ -236,7 +273,7 @@
M3GNativeWindow wnd)
{
EGLSurface surf;
- EGLConfig config = m3gQueryEGLConfig(format, bufferBits, EGL_WINDOW_BIT);
+ EGLConfig config = m3gQueryEGLConfig(format, bufferBits, EGL_WINDOW_BIT, NULL);
if (!config) {
return NULL;
@@ -272,7 +309,7 @@
M3GNativeBitmap bmp)
{
EGLSurface surf;
- EGLConfig config = m3gQueryEGLConfig(format, bufferBits, EGL_PIXMAP_BIT);
+ EGLConfig config = m3gQueryEGLConfig(format, bufferBits, EGL_PIXMAP_BIT, bmp);
if (!config) {
return NULL;
@@ -317,7 +354,7 @@
attrib[3] = height;
attrib[4] = EGL_NONE;
- config = m3gQueryEGLConfig(format, bufferBits, EGL_PBUFFER_BIT);
+ config = m3gQueryEGLConfig(format, bufferBits, EGL_PBUFFER_BIT, NULL);
if (!config) {
return NULL;
}
@@ -410,7 +447,7 @@
if (internalFormat == M3G_RGB8_32) {
glFormat = GL_RGBA;
}
- if (internalFormat == M3G_BGR8_32) {
+ if (internalFormat == M3G_BGR8_32 || internalFormat == M3G_ARGB8) {
glFormat = GL_RGBA;
mustConvert = M3G_TRUE;
}
@@ -714,6 +751,7 @@
M3GPixelFormat format = ctx->target.format;
M3Gbitmask bufferBits = ctx->bufferBits;
M3Gbitmask surfaceType = ctx->target.type;
+ M3GNativeBitmap bitmapHandle = ctx->target.handle;
int i;
/* Images always go via pbuffers; EGL surfaces can always be
@@ -742,7 +780,7 @@
/* No dice; must resort to querying from EGL */
- return (m3gQueryEGLConfig(format, bufferBits, (EGLint) surfaceType) != NULL);
+ return (m3gQueryEGLConfig(format, bufferBits, (EGLint) surfaceType, bitmapHandle) != NULL);
}
/*!
@@ -918,38 +956,45 @@
if (ctx->target.type == SURFACE_IMAGE) {
m3gDrawFrameBufferImage(ctx, (Image *) ctx->target.handle);
}
- else if (ctx->target.type == SURFACE_BITMAP) {
+ else if (ctx->target.type == SURFACE_BITMAP || ctx->target.type == SURFACE_MEMORY) {
M3Gubyte *src;
M3Gsizei stride;
- /* Obtain a pointer to the native bitmap and copy the data to
- * the backbuffer from there */
-
- if (m3gglLockNativeBitmap((M3GNativeBitmap) ctx->target.handle,
- &src, &stride)) {
+ M3Gint clipWidth = ctx->clip.x1 - ctx->clip.x0;
+ M3Gint clipHeight = ctx->clip.y1 - ctx->clip.y0;
+ M3Gint srcOffset;
- M3Gint clipWidth = ctx->clip.x1 - ctx->clip.x0;
- M3Gint clipHeight = ctx->clip.y1 - ctx->clip.y0;
- M3Gint srcOffset =
- (ctx->target.height - ctx->clip.y1) * stride
- + ctx->clip.x0 * m3gBytesPerPixel(ctx->target.format);
-
- m3gBlitFrameBufferPixels(
- ctx,
- ctx->clip.x0, ctx->clip.y0,
- clipWidth, clipHeight,
- ctx->target.format,
- stride,
- src + srcOffset);
-
+ if (ctx->target.type == SURFACE_BITMAP) {
+ /* Obtain a pointer to the native bitmap and copy the data to
+ * the backbuffer from there */
+ if (!m3gglLockNativeBitmap((M3GNativeBitmap) ctx->target.handle,
+ &src, &stride)) {
+ /* No dice! There's no way that we know of to copy the
+ * data between the buffers */
+ M3G_ASSERT(M3G_FALSE);
+ }
+ } else {
+ /* Memory target */
+ src = ctx->target.pixels;
+ stride = ctx->target.stride;
+ }
+
+ srcOffset =
+ (ctx->target.height - ctx->clip.y1) * stride
+ + ctx->clip.x0 * m3gBytesPerPixel(ctx->target.format);
+
+ m3gBlitFrameBufferPixels(
+ ctx,
+ ctx->clip.x0, ctx->clip.y0,
+ clipWidth, clipHeight,
+ ctx->target.format,
+ stride,
+ src + srcOffset);
+
+ if (ctx->target.type == SURFACE_BITMAP) {
m3gglReleaseNativeBitmap((M3GNativeBitmap) ctx->target.handle);
}
- else {
- /* No dice! There's no way that we know of to copy the
- * data between the buffers */
- M3G_ASSERT(M3G_FALSE);
- }
}
else {
/* Buffered rendering is not supported for window and pbuffer
@@ -969,67 +1014,75 @@
if (ctx->target.type == SURFACE_IMAGE) {
m3gCopyFrameBufferImage((Image *) ctx->target.handle);
}
- else if (ctx->target.type == SURFACE_BITMAP) {
+ else if (ctx->target.type == SURFACE_BITMAP || ctx->target.type == SURFACE_MEMORY) {
- /* We must copy the back buffer to a native bitmap: first
- * attempt a fast buffer-to-buffer copy using EGL, but if that
- * fails, obtain a pointer and do the copy ourselves */
+ M3GPixelFormat format = ctx->target.format;
+ M3Gint width = ctx->clip.x1 - ctx->clip.x0;
+ M3Gint height = ctx->clip.y1 - ctx->clip.y0;
+ M3Gint xOffset = ctx->clip.x0;
+ M3Gint yOffset = ctx->clip.y0;
+ M3Gint row;
- /* We can only do the fast copy for the full buffer */
+ M3Gubyte *dst;
+ M3Gsizei stride;
+ M3Gubyte *temp;
- M3Gbool fullClip = (ctx->clip.x0 == 0)
- && (ctx->clip.y0 <= ctx->target.height - ctx->display.height)
- && (ctx->clip.x1 >= ctx->display.width)
- && (ctx->clip.y1 >= ctx->clip.y0 + ctx->display.height);
-
- if (!fullClip || !eglCopyBuffers(eglGetDisplay(EGL_DEFAULT_DISPLAY),
- ctx->backBuffer.glSurface,
- (NativePixmapType) ctx->target.handle)) {
+ if (ctx->target.type == SURFACE_BITMAP) {
+ /* We must copy the back buffer to a native bitmap: first
+ * attempt a fast buffer-to-buffer copy using EGL, but if that
+ * fails, obtain a pointer and do the copy ourselves */
+
+ /* We can only do the fast copy for the full buffer */
+
+ M3Gbool fullClip = (ctx->clip.x0 == 0)
+ && (ctx->clip.y0 <= ctx->target.height - ctx->display.height)
+ && (ctx->clip.x1 >= ctx->display.width)
+ && (ctx->clip.y1 >= ctx->clip.y0 + ctx->display.height);
+
+ if (fullClip && eglCopyBuffers(eglGetDisplay(EGL_DEFAULT_DISPLAY),
+ ctx->backBuffer.glSurface,
+ (NativePixmapType) ctx->target.handle))
+ {
+ return;
+ }
/* Fast copy failed, try the generic approach */
-
- M3Gubyte *dst;
- M3Gsizei stride;
-
- if (m3gglLockNativeBitmap((M3GNativeBitmap) ctx->target.handle,
+ if (!m3gglLockNativeBitmap((M3GNativeBitmap) ctx->target.handle,
&dst, &stride)) {
-
- /* OK, got the pointer; now, copy a scanline at a
- * time, and we can pretty much assume conversion
- * since the fast method didn't work */
-
- M3GPixelFormat format = ctx->target.format;
- M3Gint width = ctx->clip.x1 - ctx->clip.x0;
- M3Gint height = ctx->clip.y1 - ctx->clip.y0;
- M3Gint xOffset = ctx->clip.x0;
- M3Gint yOffset = ctx->clip.y0;
- M3Gint row;
-
- M3Gubyte *temp = m3gAllocTemp(M3G_INTERFACE(ctx), width * 4);
- if (!temp) {
- return; /* out of memory */
- }
-
- dst += (ctx->target.height - (yOffset + height)) * stride
- + xOffset * m3gBytesPerPixel(format);
-
- for (row = 0; row < height; ++row) {
- glReadPixels(xOffset, yOffset + height - row - 1,
- width, 1,
- GL_RGBA, GL_UNSIGNED_BYTE,
- temp);
- m3gConvertPixels(M3G_RGBA8, temp, format, dst, width);
- dst += stride;
- }
- m3gFreeTemp(M3G_INTERFACE(ctx));
-
- m3gglReleaseNativeBitmap((M3GNativeBitmap) ctx->target.handle);
- }
- else {
/* No dice! There's no way that we know of to copy the
* data between the buffers */
M3G_ASSERT(M3G_FALSE);
}
+ } else {
+ /* Memory target */
+ dst = ctx->target.pixels;
+ stride = ctx->target.stride;
+ }
+
+ /* OK, got the pointer; now, copy a scanline at a
+ * time, and we can pretty much assume conversion
+ * since the fast method didn't work */
+
+ temp = m3gAllocTemp(M3G_INTERFACE(ctx), width * 4);
+ if (!temp) {
+ return; /* out of memory */
+ }
+
+ dst += (ctx->target.height - (yOffset + height)) * stride
+ + xOffset * m3gBytesPerPixel(format);
+
+ for (row = 0; row < height; ++row) {
+ glReadPixels(xOffset, yOffset + height - row - 1,
+ width, 1,
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ temp);
+ m3gConvertPixels(M3G_RGBA8, temp, format, dst, width);
+ dst += stride;
+ }
+ m3gFreeTemp(M3G_INTERFACE(ctx));
+
+ if (ctx->target.type == SURFACE_BITMAP) {
+ m3gglReleaseNativeBitmap((M3GNativeBitmap) ctx->target.handle);
}
}
else {
@@ -1102,24 +1155,25 @@
* done in this order so that we don't lose any shared texture
* objects when deleting a context. */
- if (surfaceTypeBits == SURFACE_EGL) {
+ //if (surfaceTypeBits == SURFACE_EGL)
+ {
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint configID;
eglQuerySurface(dpy,
- (EGLSurface) ctx->target.handle,
+ surface,//(EGLSurface) ctx->target.handle,
EGL_CONFIG_ID,
&configID);
glrc = eglCreateContext(dpy, (EGLConfig) configID, shareRc, NULL);
- M3G_ASSERT(glrc);
+ //M3G_ASSERT(glrc);
}
- else {
+ /*else {
glrc = m3gCreateGLContext(format,
bufferBits,
surfaceTypeBits,
shareRc,
&lru->surfaceTypeBits);
}
-
+ */
if (!glrc) {
m3gRaiseError(M3G_INTERFACE(ctx), M3G_OUT_OF_MEMORY);
return NULL;
@@ -1181,9 +1235,13 @@
for (i = 0; i < M3G_MAX_GL_SURFACES; ++i) {
GLSurfaceRecord *surf = &ctx->glSurface[i];
- if (surf->type == ctx->target.type
- && surf->targetHandle == ctx->target.handle
- && (ctx->bufferBits & surf->bufferBits) == ctx->bufferBits) {
+ if ((surf->type == ctx->target.type)
+ && (surf->targetHandle == ctx->target.handle)
+ && ((ctx->bufferBits & surf->bufferBits) == ctx->bufferBits)
+ && (surf->width == ctx->target.width)
+ && (surf->height == ctx->target.height)
+ && (surf->format == ctx->target.format)
+ && (surf->pixels == ctx->target.pixels)) {
surf->lastUseTime = ctx->cacheTimeStamp;
return surf->handle;
@@ -1241,6 +1299,10 @@
lru->type = ctx->target.type;
lru->targetHandle = ctx->target.handle;
lru->bufferBits = ctx->bufferBits;
+ lru->width = ctx->target.width;
+ lru->height = ctx->target.height;
+ lru->format = ctx->target.format;
+ lru->pixels = ctx->target.pixels;
lru->lastUseTime = ctx->cacheTimeStamp;
return lru->handle;
}
@@ -1302,6 +1364,8 @@
*/
static void m3gMakeGLCurrent(RenderContext *ctx)
{
+ eglBindAPI(EGL_OPENGL_ES_API);
+
if (ctx != NULL) {
EGLContext eglCtx = NULL;
if (ctx->target.buffered) {
@@ -1357,13 +1421,13 @@
M3GNativeBitmap hBitmap)
{
M3GPixelFormat format;
- M3Gint width, height;
+ M3Gint width, height, pixels;
RenderContext *ctx = (RenderContext *) hCtx;
M3G_VALIDATE_OBJECT(ctx);
M3G_LOG1(M3G_LOG_RENDERING, "Binding bitmap 0x%08X\n", (unsigned) hBitmap);
- if (!m3gglGetNativeBitmapParams(hBitmap, &format, &width, &height)) {
+ if (!m3gglGetNativeBitmapParams(hBitmap, &format, &width, &height, &pixels)) {
m3gRaiseError(M3G_INTERFACE(ctx), M3G_INVALID_OBJECT);
return;
}
@@ -1376,7 +1440,10 @@
return; /* appropriate error raised automatically */
}
- /* placeholder for bitmap target specific setup */
+ /* Set the bitmap target specific parameters */
+
+ ctx->target.pixels = (void*)pixels;
+
}
/*!
@@ -1417,28 +1484,57 @@
}
/*!
- * \brief Unsupported with OpenGL ES
+ * \brief Binds a new memory rendering target to this rendering
+ * context
+ *
+ * Upon first binding of a specific target, binding the buffer may
+ * require auxiliary data to be allocated, depending on the rendering
+ * modes set for this context. In that case, the binding will be
+ * canceled, and the function will return a non-zero value giving the
+ * number of bytes of additional memory that needs to be supplied for
+ * binding of that target to succeed. The function must then be called
+ * again and a pointer to a sufficient memory block supplied as the \c
+ * mem parameter.
+ *
+ * \param pixels NULL to signal that the frame buffer is accessed
+ * using a callback upon rendering time
*/
-/*@access EGLContext@*/
-M3G_API void m3gBindMemoryTarget(M3GRenderContext context,
- /*@shared@*/ void *pixels,
- M3Guint width, M3Guint height,
- M3GPixelFormat format,
- M3Guint stride,
- M3Guint userHandle)
+/*@access M3GGLContext@*/
+void m3gBindMemoryTarget(M3GRenderContext context,
+ /*@shared@*/ void *pixels,
+ M3Guint width, M3Guint height,
+ M3GPixelFormat format,
+ M3Guint stride,
+ M3Guint userHandle)
{
RenderContext *ctx = (RenderContext*) context;
Interface *m3g = M3G_INTERFACE(ctx);
M3G_VALIDATE_OBJECT(ctx);
- M3G_UNREF(pixels);
- M3G_UNREF(width);
- M3G_UNREF(height);
- M3G_UNREF(format);
- M3G_UNREF(stride);
- M3G_UNREF(userHandle);
+ M3G_LOG1(M3G_LOG_RENDERING, "Binding memory buffer 0x%08X\n",
+ (unsigned) pixels);
+
+ /* Check for bitmap specific errors */
+
+ if (width == 0 || height == 0 || stride < width) {
+ m3gRaiseError(m3g, M3G_INVALID_VALUE);
+ return;
+ }
+
+ /* Effect the generic target binding */
- m3gRaiseError(m3g, M3G_INVALID_OPERATION);
+ if (!m3gBindRenderTarget(ctx,
+ SURFACE_MEMORY,
+ width, height,
+ format,
+ userHandle)) {
+ return; /* appropriate error raised automatically */
+ }
+
+ /* Set the memory target specific parameters */
+
+ ctx->target.pixels = pixels;
+ ctx->target.stride = stride;
}
/*!
@@ -1515,3 +1611,24 @@
m3gDeleteGLSurfaces(ctx, (M3Gbitmask) SURFACE_WINDOW, (M3Guint) hWindow);
}
+
+/*!
+ * \brief Invalidate a previously bound memorytarget
+ *
+ * This should be called prior to deleting a memory buffer that has
+ * been used as an M3G rendering target in the past.
+ *
+ * \param hCtx M3G rendering context
+ * \param pixels pointer to the memory buffer
+ */
+M3G_API void m3gInvalidateMemoryTarget(M3GRenderContext hCtx,
+ void *pixels)
+{
+ RenderContext *ctx = (RenderContext *) hCtx;
+ M3G_VALIDATE_OBJECT(ctx);
+
+ M3G_LOG1(M3G_LOG_RENDERING, "Invalidating memory target 0x%08X\n",
+ (unsigned) pixels);
+
+ m3gDeleteGLSurfaces(ctx, (M3Gbitmask) SURFACE_MEMORY, (M3Guint) pixels);
+}