m3g/m3gcore11/src/m3g_rendercontext.inl
changeset 36 01a6848ebfd7
parent 0 5d03bc08d59c
child 45 36b2e23a8629
equal deleted inserted replaced
0:5d03bc08d59c 36:01a6848ebfd7
    24 
    24 
    25 #if defined(M3G_NGL_CONTEXT_API)
    25 #if defined(M3G_NGL_CONTEXT_API)
    26 #   error This file is for the OES API only
    26 #   error This file is for the OES API only
    27 #endif
    27 #endif
    28 
    28 
    29 #include <GLES/egl.h>
    29 #include <EGL/egl.h>
    30 #include "m3g_image.h"
    30 #include "m3g_image.h"
    31 
    31 
    32 /*----------------------------------------------------------------------
    32 /*----------------------------------------------------------------------
    33  * Private functions
    33  * Private functions
    34  *--------------------------------------------------------------------*/
    34  *--------------------------------------------------------------------*/
    38  * \brief Queries for an EGL configuration matching given M3G format
    38  * \brief Queries for an EGL configuration matching given M3G format
    39  * parameters
    39  * parameters
    40  */
    40  */
    41 static EGLConfig m3gQueryEGLConfig(M3Genum format,
    41 static EGLConfig m3gQueryEGLConfig(M3Genum format,
    42                                    M3Gbitmask bufferBits,
    42                                    M3Gbitmask bufferBits,
    43                                    EGLint surfaceBits)
    43                                    EGLint surfaceBits,
    44 {
    44                                    M3GNativeBitmap bitmapHandle)
    45     struct { int attrib, value; } attribs[9];
    45 {
       
    46     struct { int attrib, value; } attribs[10];
    46     int samples;
    47     int samples;
    47 
    48 
    48     /* Determine color depth */
    49     /* Determine color depth */
    49     
    50     
    50     attribs[0].attrib = EGL_RED_SIZE;
    51     attribs[0].attrib = EGL_RED_SIZE;
    91     /* Set target surface type mask */
    92     /* Set target surface type mask */
    92     
    93     
    93     attribs[5].attrib = EGL_SURFACE_TYPE;
    94     attribs[5].attrib = EGL_SURFACE_TYPE;
    94     attribs[5].value = surfaceBits;
    95     attribs[5].value = surfaceBits;
    95 
    96 
    96     /* Try to get multisampling if requested */
    97 
    97 
    98     if (bitmapHandle) {
    98     attribs[6].attrib = EGL_SAMPLE_BUFFERS;
    99         /* This attribute is matched only for pixmap targets */
    99     attribs[7].attrib = EGL_SAMPLES;
   100         attribs[6].attrib = EGL_MATCH_NATIVE_PIXMAP;
   100     attribs[8].attrib = EGL_NONE;
   101         attribs[6].value = bitmapHandle;
   101 
   102 
       
   103         /* Try to get multisampling if requested */
       
   104 
       
   105         attribs[7].attrib = EGL_SAMPLE_BUFFERS;
       
   106         attribs[8].attrib = EGL_SAMPLES;
       
   107 
       
   108         attribs[9].attrib = EGL_NONE;
       
   109     } else {
       
   110         /* Try to get multisampling if requested */
       
   111 
       
   112         attribs[6].attrib = EGL_SAMPLE_BUFFERS;
       
   113         attribs[7].attrib = EGL_SAMPLES;
       
   114 
       
   115         attribs[8].attrib = EGL_NONE;
       
   116     }
       
   117     
       
   118     
   102     /* Try 4 samples if multisampling enabled, then 2, then 1 */
   119     /* Try 4 samples if multisampling enabled, then 2, then 1 */
   103     
   120     
   104     samples = (bufferBits & M3G_MULTISAMPLE_BUFFER_BIT) ? 4 : 1;
   121     samples = (bufferBits & M3G_MULTISAMPLE_BUFFER_BIT) ? 4 : 1;
   105     for ( ; samples > 0; samples >>= 1) {
   122     for ( ; samples > 0; samples >>= 1) {
   106         
   123         
   107         if (samples > 1) {
   124         if (bitmapHandle) {
   108             attribs[6].value = 1;
   125             if (samples > 1) {
   109             attribs[7].value = samples;
   126                 attribs[7].value = 1;
   110         }
   127                 attribs[8].value = samples;
   111         else {
   128             }
   112             attribs[6].value = EGL_FALSE;
   129             else {
   113             attribs[7].value = 0;
   130                 attribs[7].value = EGL_FALSE;
       
   131                 attribs[8].value = 0;
       
   132             }
       
   133         } else {
       
   134             if (samples > 1) {
       
   135                 attribs[6].value = 1;
       
   136                 attribs[7].value = samples;
       
   137             }
       
   138             else {
       
   139                 attribs[6].value = EGL_FALSE;
       
   140                 attribs[7].value = 0;
       
   141             }
   114         }
   142         }
   115 
   143 
   116         /* Get the first matching config; according to EGL sorting
   144         /* Get the first matching config; according to EGL sorting
   117          * rules, this should be an accelerated one if possible */
   145          * rules, this should be an accelerated one if possible */
   118         {
   146         {
   119             EGLConfig config;
   147             EGLConfig config;
   120             int numConfigs;
   148             int numConfigs;  
       
   149             EGLint error;            
       
   150         
   121             eglChooseConfig(eglGetDisplay(EGL_DEFAULT_DISPLAY),
   151             eglChooseConfig(eglGetDisplay(EGL_DEFAULT_DISPLAY),
   122                             (const int *) attribs,
   152                             (const int *) attribs,
   123                             &config, 1,
   153                             &config, 1,
   124                             &numConfigs);
   154                             &numConfigs);
   125             
   155             
   126             M3G_ASSERT(eglGetError() == EGL_SUCCESS);
   156             error = eglGetError();
       
   157             if (error != EGL_SUCCESS) {
       
   158                 M3G_LOG1(M3G_LOG_FATAL_ERRORS, "eglChooseConfig  failed: %d\n", error);
       
   159             }
       
   160             
       
   161             
       
   162             M3G_ASSERT(error == EGL_SUCCESS);
   127 
   163 
   128             /* If we got a config, return that; otherwise, drop the
   164             /* If we got a config, return that; otherwise, drop the
   129              * number of multisampling samples and try again, or
   165              * number of multisampling samples and try again, or
   130              * return NULL for no config if we already have zero
   166              * return NULL for no config if we already have zero
   131              * samples */
   167              * samples */
   152  */
   188  */
   153 static void m3gInitializeEGL(void)
   189 static void m3gInitializeEGL(void)
   154 {
   190 {
   155     M3G_LOG(M3G_LOG_INTERFACE, "Initializing EGL\n");
   191     M3G_LOG(M3G_LOG_INTERFACE, "Initializing EGL\n");
   156     eglInitialize(eglGetDisplay(EGL_DEFAULT_DISPLAY), NULL, NULL);
   192     eglInitialize(eglGetDisplay(EGL_DEFAULT_DISPLAY), NULL, NULL);
       
   193     eglBindAPI(EGL_OPENGL_ES_API);
   157 }
   194 }
   158 
   195 
   159 /*!
   196 /*!
   160  * \internal
   197  * \internal
   161  * \brief Terminates EGL
   198  * \brief Terminates EGL
   168 
   205 
   169 /*!
   206 /*!
   170  * \internal
   207  * \internal
   171  * \brief Creates a new EGL context
   208  * \brief Creates a new EGL context
   172  */
   209  */
   173 static EGLContext m3gCreateGLContext(M3Genum format,
   210 /*static EGLContext m3gCreateGLContext(M3Genum format,
   174                                      M3Gbitmask bufferBits,
   211                                      M3Gbitmask bufferBits,
   175                                      M3Gbitmask reqSurfaceBits,
   212                                      M3Gbitmask reqSurfaceBits,
   176                                      EGLContext share,
   213                                      EGLContext share,
   177                                      M3Gbitmask *outSurfaceBits)
   214                                      M3Gbitmask *outSurfaceBits)
   178 {
   215 {
   179     EGLContext ctx;
   216     EGLContext ctx;
   180     EGLConfig config;
   217     EGLConfig config;
   181 
   218 
   182     M3G_ASSERT((reqSurfaceBits & ~(EGL_PIXMAP_BIT|EGL_PBUFFER_BIT|EGL_WINDOW_BIT)) == 0);
   219     M3G_ASSERT((reqSurfaceBits & ~(EGL_PIXMAP_BIT|EGL_PBUFFER_BIT|EGL_WINDOW_BIT)) == 0);
   183     
   220     
   184     config = m3gQueryEGLConfig(format, bufferBits, reqSurfaceBits);
   221     config = m3gQueryEGLConfig(format, bufferBits, reqSurfaceBits, NULL);
   185     
   222     
   186     if (!config || !eglGetConfigAttrib(eglGetDisplay(EGL_DEFAULT_DISPLAY),
   223     if (!config || !eglGetConfigAttrib(eglGetDisplay(EGL_DEFAULT_DISPLAY),
   187                                        config,
   224                                        config,
   188                                        EGL_SURFACE_TYPE,
   225                                        EGL_SURFACE_TYPE,
   189                                        (EGLint *) outSurfaceBits)) {
   226                                        (EGLint *) outSurfaceBits)) {
   203 #   endif
   240 #   endif
   204 
   241 
   205     M3G_LOG1(M3G_LOG_OBJECTS, "New GL context 0x%08X\n", (unsigned) ctx);
   242     M3G_LOG1(M3G_LOG_OBJECTS, "New GL context 0x%08X\n", (unsigned) ctx);
   206     return ctx;
   243     return ctx;
   207 }
   244 }
   208 
   245 */
   209 /*!
   246 /*!
   210  * \internal
   247  * \internal
   211  * \brief Deletes an EGL context
   248  * \brief Deletes an EGL context
   212  */
   249  */
   213 static void m3gDeleteGLContext(EGLContext ctx)
   250 static void m3gDeleteGLContext(EGLContext ctx)
   234 static EGLSurface m3gCreateWindowSurface(M3Genum format,
   271 static EGLSurface m3gCreateWindowSurface(M3Genum format,
   235                                          M3Gbitmask bufferBits,
   272                                          M3Gbitmask bufferBits,
   236                                          M3GNativeWindow wnd)
   273                                          M3GNativeWindow wnd)
   237 {
   274 {
   238     EGLSurface surf;
   275     EGLSurface surf;
   239     EGLConfig config = m3gQueryEGLConfig(format, bufferBits, EGL_WINDOW_BIT);
   276     EGLConfig config = m3gQueryEGLConfig(format, bufferBits, EGL_WINDOW_BIT, NULL);
   240     
   277     
   241     if (!config) {
   278     if (!config) {
   242         return NULL;
   279         return NULL;
   243     }
   280     }
   244 
   281 
   270 static EGLSurface m3gCreateBitmapSurface(M3Genum format,
   307 static EGLSurface m3gCreateBitmapSurface(M3Genum format,
   271                                          M3Gbitmask bufferBits,
   308                                          M3Gbitmask bufferBits,
   272                                          M3GNativeBitmap bmp)
   309                                          M3GNativeBitmap bmp)
   273 {
   310 {
   274     EGLSurface surf;
   311     EGLSurface surf;
   275     EGLConfig config = m3gQueryEGLConfig(format, bufferBits, EGL_PIXMAP_BIT);
   312     EGLConfig config = m3gQueryEGLConfig(format, bufferBits, EGL_PIXMAP_BIT, bmp);
   276     
   313     
   277     if (!config) {
   314     if (!config) {
   278         return NULL;
   315         return NULL;
   279     }
   316     }
   280     
   317     
   315     attrib[1] = width;
   352     attrib[1] = width;
   316     attrib[2] = EGL_HEIGHT;
   353     attrib[2] = EGL_HEIGHT;
   317     attrib[3] = height;
   354     attrib[3] = height;
   318     attrib[4] = EGL_NONE;
   355     attrib[4] = EGL_NONE;
   319     
   356     
   320     config = m3gQueryEGLConfig(format, bufferBits, EGL_PBUFFER_BIT);
   357     config = m3gQueryEGLConfig(format, bufferBits, EGL_PBUFFER_BIT, NULL);
   321     if (!config) {
   358     if (!config) {
   322         return NULL;
   359         return NULL;
   323     }
   360     }
   324 
   361 
   325     surf = eglCreatePbufferSurface(eglGetDisplay(EGL_DEFAULT_DISPLAY),
   362     surf = eglCreatePbufferSurface(eglGetDisplay(EGL_DEFAULT_DISPLAY),
   408         return;
   445         return;
   409     }
   446     }
   410     if (internalFormat == M3G_RGB8_32) {
   447     if (internalFormat == M3G_RGB8_32) {
   411         glFormat = GL_RGBA;
   448         glFormat = GL_RGBA;
   412     }
   449     }
   413     if (internalFormat == M3G_BGR8_32) {
   450     if (internalFormat == M3G_BGR8_32 || internalFormat == M3G_ARGB8) {
   414         glFormat = GL_RGBA;
   451         glFormat = GL_RGBA;
   415         mustConvert = M3G_TRUE;
   452         mustConvert = M3G_TRUE;
   416     }
   453     }
   417 
   454 
   418     /* Tweak tile size to avoid using excessive amounts of memory for
   455     /* Tweak tile size to avoid using excessive amounts of memory for
   712 static M3Gbool m3gCanDirectRender(const RenderContext *ctx)
   749 static M3Gbool m3gCanDirectRender(const RenderContext *ctx)
   713 {
   750 {
   714     M3GPixelFormat format = ctx->target.format;
   751     M3GPixelFormat format = ctx->target.format;
   715     M3Gbitmask bufferBits = ctx->bufferBits;
   752     M3Gbitmask bufferBits = ctx->bufferBits;
   716     M3Gbitmask surfaceType = ctx->target.type;
   753     M3Gbitmask surfaceType = ctx->target.type;
       
   754     M3GNativeBitmap bitmapHandle = ctx->target.handle;
   717     int i;
   755     int i;
   718 
   756 
   719     /* Images always go via pbuffers; EGL surfaces can always be
   757     /* Images always go via pbuffers; EGL surfaces can always be
   720      * rendered to */
   758      * rendered to */
   721     
   759     
   740         }
   778         }
   741     }
   779     }
   742 
   780 
   743     /* No dice; must resort to querying from EGL */
   781     /* No dice; must resort to querying from EGL */
   744 
   782 
   745     return (m3gQueryEGLConfig(format, bufferBits, (EGLint) surfaceType) != NULL);
   783     return (m3gQueryEGLConfig(format, bufferBits, (EGLint) surfaceType, bitmapHandle) != NULL);
   746 }
   784 }
   747 
   785 
   748 /*!
   786 /*!
   749  * \internal
   787  * \internal
   750  * \brief Ensures that a sufficient back buffer exists
   788  * \brief Ensures that a sufficient back buffer exists
   916 static void m3gUpdateBackBuffer(RenderContext *ctx)
   954 static void m3gUpdateBackBuffer(RenderContext *ctx)
   917 {
   955 {
   918     if (ctx->target.type == SURFACE_IMAGE) {
   956     if (ctx->target.type == SURFACE_IMAGE) {
   919         m3gDrawFrameBufferImage(ctx, (Image *) ctx->target.handle);
   957         m3gDrawFrameBufferImage(ctx, (Image *) ctx->target.handle);
   920     }
   958     }
   921     else if (ctx->target.type == SURFACE_BITMAP) {
   959     else if (ctx->target.type == SURFACE_BITMAP || ctx->target.type == SURFACE_MEMORY) {
   922 
   960 
   923         M3Gubyte *src;
   961         M3Gubyte *src;
   924         M3Gsizei stride;
   962         M3Gsizei stride;
   925 
   963 
   926         /* Obtain a pointer to the native bitmap and copy the data to
   964         M3Gint clipWidth = ctx->clip.x1 - ctx->clip.x0;
   927          * the backbuffer from there */
   965         M3Gint clipHeight = ctx->clip.y1 - ctx->clip.y0;
   928         
   966         M3Gint srcOffset;
   929         if (m3gglLockNativeBitmap((M3GNativeBitmap) ctx->target.handle,
   967 
   930                                   &src, &stride)) {
   968         if (ctx->target.type == SURFACE_BITMAP) {
   931 
   969             /* Obtain a pointer to the native bitmap and copy the data to
   932             M3Gint clipWidth = ctx->clip.x1 - ctx->clip.x0;
   970              * the backbuffer from there */
   933             M3Gint clipHeight = ctx->clip.y1 - ctx->clip.y0;
   971             if (!m3gglLockNativeBitmap((M3GNativeBitmap) ctx->target.handle,
   934             M3Gint srcOffset =
   972                                       &src, &stride)) {
   935                 (ctx->target.height - ctx->clip.y1) * stride
   973                 /* No dice! There's no way that we know of to copy the
   936                 + ctx->clip.x0 * m3gBytesPerPixel(ctx->target.format);
   974                  * data between the buffers */
   937             
   975                 M3G_ASSERT(M3G_FALSE);
   938             m3gBlitFrameBufferPixels(
   976             }
   939                 ctx,
   977         } else {
   940                 ctx->clip.x0, ctx->clip.y0,
   978             /* Memory target */
   941                 clipWidth, clipHeight,
   979             src = ctx->target.pixels;
   942                 ctx->target.format,
   980             stride = ctx->target.stride;
   943                 stride,
   981         }
   944                 src + srcOffset);
   982 
   945                 
   983         srcOffset =
       
   984             (ctx->target.height - ctx->clip.y1) * stride
       
   985             + ctx->clip.x0 * m3gBytesPerPixel(ctx->target.format);
       
   986         
       
   987         m3gBlitFrameBufferPixels(
       
   988             ctx,
       
   989             ctx->clip.x0, ctx->clip.y0,
       
   990             clipWidth, clipHeight,
       
   991             ctx->target.format,
       
   992             stride,
       
   993             src + srcOffset);
       
   994 
       
   995         if (ctx->target.type == SURFACE_BITMAP) {
   946             m3gglReleaseNativeBitmap((M3GNativeBitmap) ctx->target.handle);
   996             m3gglReleaseNativeBitmap((M3GNativeBitmap) ctx->target.handle);
   947         }
       
   948         else {
       
   949             /* No dice! There's no way that we know of to copy the
       
   950              * data between the buffers */
       
   951             M3G_ASSERT(M3G_FALSE);
       
   952         }
   997         }
   953     }
   998     }
   954     else {
   999     else {
   955         /* Buffered rendering is not supported for window and pbuffer
  1000         /* Buffered rendering is not supported for window and pbuffer
   956          * targets */
  1001          * targets */
   967 static void m3gUpdateTargetBuffer(RenderContext *ctx)
  1012 static void m3gUpdateTargetBuffer(RenderContext *ctx)
   968 {
  1013 {
   969     if (ctx->target.type == SURFACE_IMAGE) {
  1014     if (ctx->target.type == SURFACE_IMAGE) {
   970         m3gCopyFrameBufferImage((Image *) ctx->target.handle);
  1015         m3gCopyFrameBufferImage((Image *) ctx->target.handle);
   971     }
  1016     }
   972     else if (ctx->target.type == SURFACE_BITMAP) {
  1017     else if (ctx->target.type == SURFACE_BITMAP || ctx->target.type == SURFACE_MEMORY) {
   973         
  1018         
   974         /* We must copy the back buffer to a native bitmap: first
  1019         M3GPixelFormat format = ctx->target.format;
   975          * attempt a fast buffer-to-buffer copy using EGL, but if that
  1020         M3Gint width = ctx->clip.x1 - ctx->clip.x0;
   976          * fails, obtain a pointer and do the copy ourselves */
  1021         M3Gint height = ctx->clip.y1 - ctx->clip.y0;
   977 
  1022         M3Gint xOffset = ctx->clip.x0;
   978         /* We can only do the fast copy for the full buffer */
  1023         M3Gint yOffset = ctx->clip.y0;
   979 
  1024         M3Gint row;
   980         M3Gbool fullClip = (ctx->clip.x0 == 0)
  1025 
   981             && (ctx->clip.y0 <= ctx->target.height - ctx->display.height)
  1026         M3Gubyte *dst;
   982             && (ctx->clip.x1 >= ctx->display.width)
  1027         M3Gsizei stride;
   983             && (ctx->clip.y1 >= ctx->clip.y0 + ctx->display.height);
  1028         M3Gubyte *temp;
   984         
  1029 
   985         if (!fullClip || !eglCopyBuffers(eglGetDisplay(EGL_DEFAULT_DISPLAY),
  1030         if (ctx->target.type == SURFACE_BITMAP) {
   986                                          ctx->backBuffer.glSurface,
  1031             /* We must copy the back buffer to a native bitmap: first
   987                                          (NativePixmapType) ctx->target.handle)) {
  1032              * attempt a fast buffer-to-buffer copy using EGL, but if that
       
  1033              * fails, obtain a pointer and do the copy ourselves */
       
  1034 
       
  1035             /* We can only do the fast copy for the full buffer */
       
  1036 
       
  1037             M3Gbool fullClip = (ctx->clip.x0 == 0)
       
  1038                 && (ctx->clip.y0 <= ctx->target.height - ctx->display.height)
       
  1039                 && (ctx->clip.x1 >= ctx->display.width)
       
  1040                 && (ctx->clip.y1 >= ctx->clip.y0 + ctx->display.height);
       
  1041             
       
  1042             if (fullClip && eglCopyBuffers(eglGetDisplay(EGL_DEFAULT_DISPLAY),
       
  1043                                              ctx->backBuffer.glSurface,
       
  1044                                              (NativePixmapType) ctx->target.handle)) 
       
  1045             {
       
  1046                 return;
       
  1047             }
   988             
  1048             
   989             /* Fast copy failed, try the generic approach */
  1049             /* Fast copy failed, try the generic approach */
   990 
  1050             if (!m3gglLockNativeBitmap((M3GNativeBitmap) ctx->target.handle,
   991             M3Gubyte *dst;
       
   992             M3Gsizei stride;
       
   993             
       
   994             if (m3gglLockNativeBitmap((M3GNativeBitmap) ctx->target.handle,
       
   995                                       &dst, &stride)) {
  1051                                       &dst, &stride)) {
   996                 
       
   997                 /* OK, got the pointer; now, copy a scanline at a
       
   998                  * time, and we can pretty much assume conversion
       
   999                  * since the fast method didn't work */
       
  1000 
       
  1001                 M3GPixelFormat format = ctx->target.format;
       
  1002                 M3Gint width = ctx->clip.x1 - ctx->clip.x0;
       
  1003                 M3Gint height = ctx->clip.y1 - ctx->clip.y0;
       
  1004                 M3Gint xOffset = ctx->clip.x0;
       
  1005                 M3Gint yOffset = ctx->clip.y0;
       
  1006                 M3Gint row;
       
  1007 
       
  1008                 M3Gubyte *temp = m3gAllocTemp(M3G_INTERFACE(ctx), width * 4);
       
  1009                 if (!temp) {
       
  1010                     return; /* out of memory */
       
  1011                 }
       
  1012 
       
  1013                 dst += (ctx->target.height - (yOffset + height)) * stride
       
  1014                     + xOffset * m3gBytesPerPixel(format);
       
  1015                 
       
  1016                 for (row = 0; row < height; ++row) {
       
  1017                     glReadPixels(xOffset, yOffset + height - row - 1,
       
  1018                                  width, 1,
       
  1019                                  GL_RGBA, GL_UNSIGNED_BYTE,
       
  1020                                  temp);
       
  1021                     m3gConvertPixels(M3G_RGBA8, temp, format, dst, width);
       
  1022                     dst += stride;
       
  1023                 }
       
  1024                 m3gFreeTemp(M3G_INTERFACE(ctx));
       
  1025                 
       
  1026                 m3gglReleaseNativeBitmap((M3GNativeBitmap) ctx->target.handle);
       
  1027             }
       
  1028             else {
       
  1029                 /* No dice! There's no way that we know of to copy the
  1052                 /* No dice! There's no way that we know of to copy the
  1030                  * data between the buffers */
  1053                  * data between the buffers */
  1031                 M3G_ASSERT(M3G_FALSE);
  1054                 M3G_ASSERT(M3G_FALSE);
  1032             }
  1055             }
       
  1056         } else {
       
  1057             /* Memory target */
       
  1058             dst = ctx->target.pixels;
       
  1059             stride = ctx->target.stride;
       
  1060         }
       
  1061                 
       
  1062         /* OK, got the pointer; now, copy a scanline at a
       
  1063          * time, and we can pretty much assume conversion
       
  1064          * since the fast method didn't work */
       
  1065 
       
  1066         temp = m3gAllocTemp(M3G_INTERFACE(ctx), width * 4);
       
  1067         if (!temp) {
       
  1068             return; /* out of memory */
       
  1069         }
       
  1070 
       
  1071         dst += (ctx->target.height - (yOffset + height)) * stride
       
  1072             + xOffset * m3gBytesPerPixel(format);
       
  1073         
       
  1074         for (row = 0; row < height; ++row) {
       
  1075             glReadPixels(xOffset, yOffset + height - row - 1,
       
  1076                          width, 1,
       
  1077                          GL_RGBA, GL_UNSIGNED_BYTE,
       
  1078                          temp);
       
  1079             m3gConvertPixels(M3G_RGBA8, temp, format, dst, width);
       
  1080             dst += stride;
       
  1081         }
       
  1082         m3gFreeTemp(M3G_INTERFACE(ctx));
       
  1083 
       
  1084         if (ctx->target.type == SURFACE_BITMAP) {
       
  1085             m3gglReleaseNativeBitmap((M3GNativeBitmap) ctx->target.handle);
  1033         }
  1086         }
  1034     }
  1087     }
  1035     else {
  1088     else {
  1036         /* Buffered rendering is not supported for window and pbuffer
  1089         /* Buffered rendering is not supported for window and pbuffer
  1037          * targets */
  1090          * targets */
  1100 
  1153 
  1101         /* Create a new GL context, then delete the LRU one. This is
  1154         /* Create a new GL context, then delete the LRU one. This is
  1102          * done in this order so that we don't lose any shared texture
  1155          * done in this order so that we don't lose any shared texture
  1103          * objects when deleting a context. */
  1156          * objects when deleting a context. */
  1104 
  1157 
  1105         if (surfaceTypeBits == SURFACE_EGL) {
  1158         //if (surfaceTypeBits == SURFACE_EGL) 
       
  1159         {
  1106             EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  1160             EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  1107             EGLint configID;
  1161             EGLint configID;
  1108             eglQuerySurface(dpy,
  1162             eglQuerySurface(dpy,
  1109                             (EGLSurface) ctx->target.handle,
  1163                             surface,//(EGLSurface) ctx->target.handle,
  1110                             EGL_CONFIG_ID,
  1164                             EGL_CONFIG_ID,
  1111                             &configID);
  1165                             &configID);
  1112             glrc = eglCreateContext(dpy, (EGLConfig) configID, shareRc, NULL);
  1166             glrc = eglCreateContext(dpy, (EGLConfig) configID, shareRc, NULL);
  1113             M3G_ASSERT(glrc);
  1167             //M3G_ASSERT(glrc);
  1114         }
  1168         }
  1115         else {
  1169         /*else {
  1116             glrc = m3gCreateGLContext(format,
  1170             glrc = m3gCreateGLContext(format,
  1117                                       bufferBits,
  1171                                       bufferBits,
  1118                                       surfaceTypeBits,
  1172                                       surfaceTypeBits,
  1119                                       shareRc,
  1173                                       shareRc,
  1120                                       &lru->surfaceTypeBits);
  1174                                       &lru->surfaceTypeBits);
  1121         }
  1175         }
  1122         
  1176         */
  1123         if (!glrc) {
  1177         if (!glrc) {
  1124             m3gRaiseError(M3G_INTERFACE(ctx), M3G_OUT_OF_MEMORY);
  1178             m3gRaiseError(M3G_INTERFACE(ctx), M3G_OUT_OF_MEMORY);
  1125             return NULL;
  1179             return NULL;
  1126         }
  1180         }
  1127         if (lru->handle) {
  1181         if (lru->handle) {
  1179     /* Find the first matching surface and return it */
  1233     /* Find the first matching surface and return it */
  1180     
  1234     
  1181     for (i = 0; i < M3G_MAX_GL_SURFACES; ++i) {
  1235     for (i = 0; i < M3G_MAX_GL_SURFACES; ++i) {
  1182         GLSurfaceRecord *surf = &ctx->glSurface[i];
  1236         GLSurfaceRecord *surf = &ctx->glSurface[i];
  1183         
  1237         
  1184         if (surf->type == ctx->target.type
  1238         if ((surf->type == ctx->target.type)
  1185             && surf->targetHandle == ctx->target.handle
  1239             && (surf->targetHandle == ctx->target.handle)
  1186             && (ctx->bufferBits & surf->bufferBits) == ctx->bufferBits) {
  1240             && ((ctx->bufferBits & surf->bufferBits) == ctx->bufferBits)
       
  1241             && (surf->width == ctx->target.width)
       
  1242             && (surf->height == ctx->target.height)
       
  1243             && (surf->format == ctx->target.format)
       
  1244             && (surf->pixels == ctx->target.pixels)) {
  1187             
  1245             
  1188             surf->lastUseTime = ctx->cacheTimeStamp;
  1246             surf->lastUseTime = ctx->cacheTimeStamp;
  1189             return surf->handle;
  1247             return surf->handle;
  1190         }
  1248         }
  1191     }
  1249     }
  1239 
  1297 
  1240         if (lru->handle) {
  1298         if (lru->handle) {
  1241             lru->type         = ctx->target.type;
  1299             lru->type         = ctx->target.type;
  1242             lru->targetHandle = ctx->target.handle;
  1300             lru->targetHandle = ctx->target.handle;
  1243             lru->bufferBits   = ctx->bufferBits;
  1301             lru->bufferBits   = ctx->bufferBits;
       
  1302             lru->width        = ctx->target.width;
       
  1303             lru->height       = ctx->target.height;
       
  1304             lru->format       = ctx->target.format;
       
  1305             lru->pixels       = ctx->target.pixels;
  1244             lru->lastUseTime  = ctx->cacheTimeStamp;
  1306             lru->lastUseTime  = ctx->cacheTimeStamp;
  1245             return lru->handle;
  1307             return lru->handle;
  1246         }
  1308         }
  1247 
  1309 
  1248         /* No surface created, likely due to running out of memory;
  1310         /* No surface created, likely due to running out of memory;
  1300  * \internal
  1362  * \internal
  1301  * \brief Makes an OpenGL context current to the current rendering target
  1363  * \brief Makes an OpenGL context current to the current rendering target
  1302  */
  1364  */
  1303 static void m3gMakeGLCurrent(RenderContext *ctx)
  1365 static void m3gMakeGLCurrent(RenderContext *ctx)
  1304 {
  1366 {
       
  1367     eglBindAPI(EGL_OPENGL_ES_API);
       
  1368 
  1305     if (ctx != NULL) {
  1369     if (ctx != NULL) {
  1306         EGLContext eglCtx = NULL;
  1370         EGLContext eglCtx = NULL;
  1307         if (ctx->target.buffered) {
  1371         if (ctx->target.buffered) {
  1308             eglCtx = m3gSelectGLContext(
  1372             eglCtx = m3gSelectGLContext(
  1309                 ctx,
  1373                 ctx,
  1355  */
  1419  */
  1356 void m3gBindBitmapTarget(M3GRenderContext hCtx,
  1420 void m3gBindBitmapTarget(M3GRenderContext hCtx,
  1357                          M3GNativeBitmap hBitmap)
  1421                          M3GNativeBitmap hBitmap)
  1358 {
  1422 {
  1359     M3GPixelFormat format;
  1423     M3GPixelFormat format;
  1360     M3Gint width, height;
  1424     M3Gint width, height, pixels;
  1361     RenderContext *ctx = (RenderContext *) hCtx;
  1425     RenderContext *ctx = (RenderContext *) hCtx;
  1362     M3G_VALIDATE_OBJECT(ctx);
  1426     M3G_VALIDATE_OBJECT(ctx);
  1363     
  1427     
  1364     M3G_LOG1(M3G_LOG_RENDERING, "Binding bitmap 0x%08X\n", (unsigned) hBitmap);
  1428     M3G_LOG1(M3G_LOG_RENDERING, "Binding bitmap 0x%08X\n", (unsigned) hBitmap);
  1365     
  1429     
  1366     if (!m3gglGetNativeBitmapParams(hBitmap, &format, &width, &height)) {
  1430     if (!m3gglGetNativeBitmapParams(hBitmap, &format, &width, &height, &pixels)) {
  1367         m3gRaiseError(M3G_INTERFACE(ctx), M3G_INVALID_OBJECT);
  1431         m3gRaiseError(M3G_INTERFACE(ctx), M3G_INVALID_OBJECT);
  1368         return;
  1432         return;
  1369     }
  1433     }
  1370 
  1434 
  1371     if (!m3gBindRenderTarget(ctx,
  1435     if (!m3gBindRenderTarget(ctx,
  1374                              format,
  1438                              format,
  1375                              hBitmap)) {
  1439                              hBitmap)) {
  1376         return; /* appropriate error raised automatically */
  1440         return; /* appropriate error raised automatically */
  1377     }
  1441     }
  1378 
  1442 
  1379     /* placeholder for bitmap target specific setup */
  1443     /* Set the bitmap target specific parameters */
       
  1444     
       
  1445     ctx->target.pixels = (void*)pixels;
       
  1446 
  1380 }
  1447 }
  1381 
  1448 
  1382 /*!
  1449 /*!
  1383  * \brief Binds an external EGL surface as a rendering target
  1450  * \brief Binds an external EGL surface as a rendering target
  1384  *
  1451  *
  1415         /* placeholder for target type specific setup */
  1482         /* placeholder for target type specific setup */
  1416     }
  1483     }
  1417 }
  1484 }
  1418 
  1485 
  1419 /*!
  1486 /*!
  1420  * \brief Unsupported with OpenGL ES
  1487  * \brief Binds a new memory rendering target to this rendering
  1421  */
  1488  * context
  1422 /*@access EGLContext@*/
  1489  *
  1423 M3G_API void m3gBindMemoryTarget(M3GRenderContext context,
  1490  * Upon first binding of a specific target, binding the buffer may
  1424                                  /*@shared@*/ void *pixels,
  1491  * require auxiliary data to be allocated, depending on the rendering
  1425                                  M3Guint width, M3Guint height,
  1492  * modes set for this context. In that case, the binding will be
  1426                                  M3GPixelFormat format,
  1493  * canceled, and the function will return a non-zero value giving the
  1427                                  M3Guint stride,
  1494  * number of bytes of additional memory that needs to be supplied for
  1428                                  M3Guint userHandle)
  1495  * binding of that target to succeed. The function must then be called
       
  1496  * again and a pointer to a sufficient memory block supplied as the \c
       
  1497  * mem parameter.
       
  1498  *
       
  1499  * \param pixels NULL to signal that the frame buffer is accessed
       
  1500  * using a callback upon rendering time
       
  1501  */
       
  1502 /*@access M3GGLContext@*/
       
  1503 void m3gBindMemoryTarget(M3GRenderContext context,
       
  1504                          /*@shared@*/ void *pixels,
       
  1505                          M3Guint width, M3Guint height,
       
  1506                          M3GPixelFormat format,
       
  1507                          M3Guint stride,
       
  1508                          M3Guint userHandle)
  1429 {
  1509 {
  1430     RenderContext *ctx = (RenderContext*) context;
  1510     RenderContext *ctx = (RenderContext*) context;
  1431     Interface *m3g = M3G_INTERFACE(ctx);
  1511     Interface *m3g = M3G_INTERFACE(ctx);
  1432     M3G_VALIDATE_OBJECT(ctx);
  1512     M3G_VALIDATE_OBJECT(ctx);
  1433 
  1513 
  1434     M3G_UNREF(pixels);
  1514     M3G_LOG1(M3G_LOG_RENDERING, "Binding memory buffer 0x%08X\n",
  1435     M3G_UNREF(width);
  1515              (unsigned) pixels);
  1436     M3G_UNREF(height);
  1516     
  1437     M3G_UNREF(format);
  1517     /* Check for bitmap specific errors */
  1438     M3G_UNREF(stride);
  1518     
  1439     M3G_UNREF(userHandle);
  1519     if (width == 0 || height == 0 || stride < width) {
  1440     
  1520         m3gRaiseError(m3g, M3G_INVALID_VALUE);
  1441     m3gRaiseError(m3g, M3G_INVALID_OPERATION);
  1521         return; 
       
  1522     }
       
  1523 
       
  1524     /* Effect the generic target binding */
       
  1525     
       
  1526     if (!m3gBindRenderTarget(ctx,
       
  1527                              SURFACE_MEMORY,
       
  1528                              width, height,
       
  1529                              format,
       
  1530                              userHandle)) {
       
  1531         return; /* appropriate error raised automatically */
       
  1532     }
       
  1533 
       
  1534     /* Set the memory target specific parameters */
       
  1535     
       
  1536     ctx->target.pixels = pixels;
       
  1537     ctx->target.stride = stride;
  1442 }
  1538 }
  1443 
  1539 
  1444 /*!
  1540 /*!
  1445  * \brief
  1541  * \brief
  1446  */
  1542  */
  1513     M3G_LOG1(M3G_LOG_RENDERING, "Invalidating window 0x%08X\n",
  1609     M3G_LOG1(M3G_LOG_RENDERING, "Invalidating window 0x%08X\n",
  1514              (unsigned) hWindow);
  1610              (unsigned) hWindow);
  1515     
  1611     
  1516     m3gDeleteGLSurfaces(ctx, (M3Gbitmask) SURFACE_WINDOW, (M3Guint) hWindow);
  1612     m3gDeleteGLSurfaces(ctx, (M3Gbitmask) SURFACE_WINDOW, (M3Guint) hWindow);
  1517 }
  1613 }
       
  1614 
       
  1615 /*!
       
  1616  * \brief Invalidate a previously bound memorytarget
       
  1617  *
       
  1618  * This should be called prior to deleting a memory buffer that has
       
  1619  * been used as an M3G rendering target in the past. 
       
  1620  *
       
  1621  * \param hCtx    M3G rendering context
       
  1622  * \param pixels  pointer to the memory buffer
       
  1623  */
       
  1624 M3G_API void m3gInvalidateMemoryTarget(M3GRenderContext hCtx,
       
  1625                                        void *pixels)
       
  1626 {
       
  1627     RenderContext *ctx = (RenderContext *) hCtx;
       
  1628     M3G_VALIDATE_OBJECT(ctx);
       
  1629 
       
  1630     M3G_LOG1(M3G_LOG_RENDERING, "Invalidating memory target 0x%08X\n",
       
  1631              (unsigned) pixels);
       
  1632     
       
  1633     m3gDeleteGLSurfaces(ctx, (M3Gbitmask) SURFACE_MEMORY, (M3Guint) pixels);
       
  1634 }