hostsupport/hostopengles20/src/GLES2/context.c
branchbug235_bringup_0
changeset 53 c2ef9095503a
parent 24 a3f46bb01be2
equal deleted inserted replaced
52:39e5f73667ba 53:c2ef9095503a
       
     1 /* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2  *
       
     3  * Permission is hereby granted, free of charge, to any person obtaining a
       
     4  * copy of this software and associated documentation files (the "Software"),
       
     5  * to deal in the Software without restriction, including without limitation
       
     6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       
     7  * and/or sell copies of the Software, and to permit persons to whom the
       
     8  * Software is furnished to do so, subject to the following conditions:
       
     9  *
       
    10  * The above copyright notice and this permission notice shall be included
       
    11  * in all copies or substantial portions of the Software.
       
    12  *
       
    13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
       
    14  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
       
    16  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
       
    17  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
    18  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
    19  *
       
    20  * Initial Contributors:
       
    21  * Nokia Corporation - initial contribution.
       
    22  *
       
    23  * Contributors:
       
    24  *
       
    25  * Description:
       
    26  *
       
    27  */
       
    28 
       
    29 #include "context.h"
       
    30 #include "util.h"
       
    31 
       
    32 DGLContext* DGLContext_create(void* native_context)
       
    33 {
       
    34     DGLContext* ctx = malloc(sizeof(DGLContext));
       
    35     if(ctx == NULL)
       
    36     {
       
    37         return NULL;
       
    38     }
       
    39 
       
    40     ctx->native_context = native_context;
       
    41     ctx->initialized = GL_FALSE;
       
    42 
       
    43     return ctx;
       
    44 }
       
    45 
       
    46 GLboolean DGLContext_initialize(DGLContext* ctx)
       
    47 {
       
    48     GLint temp;
       
    49 
       
    50     DGLES2_ASSERT(ctx != NULL);
       
    51     DGLES2_ASSERT(!ctx->initialized);
       
    52 
       
    53     hglLoad(&ctx->hgl);
       
    54 
       
    55     ctx->buffers = NULL;
       
    56     ctx->shaders = NULL;
       
    57     ctx->programs = NULL;
       
    58     ctx->textures = NULL;
       
    59 	ctx->renderbuffers = NULL;
       
    60 
       
    61     ctx->hgl.GetIntegerv(GL_MAX_VERTEX_ATTRIBS, &temp);
       
    62     ctx->max_vertex_attribs = temp;
       
    63 
       
    64     ctx->vertex_arrays = malloc(ctx->max_vertex_attribs * sizeof(DGLVertexArray));
       
    65     if(ctx->vertex_arrays == NULL)
       
    66     {
       
    67         return GL_FALSE;
       
    68     }
       
    69 
       
    70     {
       
    71         int max_texture_size;
       
    72         ctx->hgl.GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
       
    73         ctx->max_texture_level = dglLog2(max_texture_size);
       
    74     }
       
    75 
       
    76     // Initialize state.
       
    77     ctx->error = GL_NO_ERROR;
       
    78     ctx->buffer_binding = 0;
       
    79 	ctx->framebuffer_binding = 0;
       
    80 	ctx->renderbuffer_binding = 0;
       
    81 
       
    82     DGLContext_bindTexture(ctx, GL_TEXTURE_2D, 0);
       
    83     DGLContext_bindTexture(ctx, GL_TEXTURE_CUBE_MAP, 0);
       
    84 
       
    85     ctx->attrib_zero[0] = 0;
       
    86     ctx->attrib_zero[1] = 0;
       
    87     ctx->attrib_zero[2] = 0;
       
    88     ctx->attrib_zero[3] = 1;
       
    89 
       
    90     // Initialize vertex arrays.
       
    91     {
       
    92         unsigned int i;
       
    93         for(i = 0; i < ctx->max_vertex_attribs; i++)
       
    94         {
       
    95             DGLVertexArray* va = &ctx->vertex_arrays[i];
       
    96 
       
    97             va->size = 4;
       
    98             va->type = GL_FLOAT;
       
    99             va->normalized = 0;
       
   100             va->stride = 0;
       
   101             va->ptr = NULL;
       
   102 
       
   103             va->enabled = 0;
       
   104             va->floatptr = NULL;
       
   105             va->buffer = NULL;
       
   106         }
       
   107     }
       
   108 
       
   109     ctx->initialized = GL_TRUE;
       
   110 
       
   111     return GL_TRUE;
       
   112 }
       
   113 
       
   114 void DGLContext_destroy(DGLContext *ctx)
       
   115 {
       
   116     DGLES2_ASSERT(ctx != NULL);
       
   117 
       
   118     if(ctx->vertex_arrays != NULL)
       
   119     {
       
   120         unsigned int i;
       
   121         for(i = 0; i < ctx->max_vertex_attribs; i++)
       
   122         {
       
   123             if(ctx->vertex_arrays[i].floatptr != NULL)
       
   124             {
       
   125                 free(ctx->vertex_arrays[i].floatptr);
       
   126                 ctx->vertex_arrays[i].floatptr = NULL;
       
   127             }
       
   128         }
       
   129         free(ctx->vertex_arrays);
       
   130         ctx->vertex_arrays = NULL;
       
   131     }
       
   132 
       
   133     // Destroy buffers
       
   134     {
       
   135         DGLBuffer* buffer = ctx->buffers;
       
   136         DGLBuffer* next;
       
   137         while(buffer != NULL)
       
   138         {
       
   139             next = (DGLBuffer*)buffer->obj.next;
       
   140             DGLBuffer_destroy(buffer);
       
   141             buffer = next;
       
   142         }
       
   143         ctx->buffers = NULL;
       
   144     }
       
   145 
       
   146     // Destroy shaders
       
   147     {
       
   148         DGLShader* shader = ctx->shaders;
       
   149         DGLShader* next;
       
   150         while(shader != NULL)
       
   151         {
       
   152             next = (DGLShader*)shader->obj.next;
       
   153             DGLShader_destroy(shader);
       
   154             shader = next;
       
   155         }
       
   156         ctx->shaders = NULL;
       
   157     }
       
   158 
       
   159     // Destroy programs
       
   160     {
       
   161         DGLProgram* program = ctx->programs;
       
   162         DGLProgram* next;
       
   163         while(program != NULL)
       
   164         {
       
   165             next = (DGLProgram*)program->obj.next;
       
   166             DGLProgram_destroy(program);
       
   167             program = next;
       
   168         }
       
   169         ctx->programs = NULL;
       
   170     }
       
   171 
       
   172     // Destroy textures
       
   173     {
       
   174         DGLTexture* texture = ctx->textures;
       
   175         DGLTexture* next;
       
   176         while(texture != NULL)
       
   177         {
       
   178             next = (DGLTexture*)texture->obj.next;
       
   179             DGLTexture_destroy(texture);
       
   180             texture = next;
       
   181         }
       
   182         ctx->textures = NULL;
       
   183     }
       
   184 
       
   185 	// Destroy renderbuffers
       
   186     {
       
   187         DGLRenderbuffer* buffer = ctx->renderbuffers;
       
   188         DGLRenderbuffer* next;
       
   189         while(buffer != NULL)
       
   190         {
       
   191             next = (DGLRenderbuffer*)buffer->obj.next;
       
   192             DGLRenderbuffer_destroy(buffer);
       
   193             buffer = next;
       
   194         }
       
   195         ctx->renderbuffers = NULL;
       
   196     }
       
   197 
       
   198     free(ctx);
       
   199 }
       
   200 
       
   201 void DGLContext_loadGL(DGLContext* ctx)
       
   202 {
       
   203     DGLES2_ASSERT(ctx != NULL);
       
   204     hglLoad(&ctx->hgl);
       
   205 }
       
   206 
       
   207 void DGLContext_setError(DGLContext* ctx, GLenum error)
       
   208 {
       
   209     DGLES2_ASSERT(ctx != NULL);
       
   210     ctx->error = error;
       
   211 }
       
   212 
       
   213 /* This function should be called before calling state-changing
       
   214    host GL functions to clear the host GL error flag. After calling
       
   215    the host GL functions, this function should be called again
       
   216    to verify the success of the state change. Only then should
       
   217    the wrapper state be modified to reflect the changes made
       
   218    in the host state. */
       
   219 GLenum DGLContext_getHostError(DGLContext* ctx)
       
   220 {
       
   221     DGLES2_ASSERT(ctx != NULL);
       
   222     {
       
   223         GLenum host_error = ctx->hgl.GetError();
       
   224         if(host_error != GL_NO_ERROR)
       
   225         {
       
   226             DGLContext_setError(ctx, host_error);
       
   227         }
       
   228         return host_error;
       
   229     }
       
   230 }
       
   231 
       
   232 GLboolean DGLContext_createBuffer(DGLContext* ctx, GLuint name)
       
   233 {
       
   234     DGLES2_ASSERT(ctx != NULL);
       
   235     DGLES2_ASSERT(DGLContext_findBuffer(ctx, name) == NULL);
       
   236     DGLES2_ASSERT(name != 0);
       
   237 
       
   238     {
       
   239         DGLBuffer* buffer = DGLBuffer_create(name);
       
   240         if(buffer == NULL)
       
   241         {
       
   242             return GL_FALSE;
       
   243         }
       
   244         DGLObject_insert((DGLObject**)&ctx->buffers, (DGLObject*)buffer);
       
   245     }
       
   246 
       
   247     return GL_TRUE;
       
   248 }
       
   249 
       
   250 void DGLContext_destroyBuffer(DGLContext *ctx, GLuint name)
       
   251 {
       
   252     DGLES2_ASSERT(ctx != NULL);
       
   253     if(name == 0)
       
   254     {
       
   255         return;
       
   256     }
       
   257 
       
   258     // Release buffer from the vertex arrays and context.
       
   259     {
       
   260         unsigned int i;
       
   261         for(i = 0; i < ctx->max_vertex_attribs; i++)
       
   262         {
       
   263             DGLVertexArray* va = &ctx->vertex_arrays[i];
       
   264             if(va->buffer != NULL && va->buffer->obj.name == name)
       
   265             {
       
   266                 va->buffer = NULL;
       
   267             }
       
   268         }
       
   269 
       
   270         if(ctx->buffer_binding == name)
       
   271         {
       
   272             ctx->buffer_binding = 0;
       
   273         }
       
   274     }
       
   275 
       
   276     {
       
   277         DGLBuffer* removed = (DGLBuffer*)DGLObject_remove((DGLObject**)&ctx->buffers, name);
       
   278         if(removed != NULL)
       
   279         {
       
   280             DGLBuffer_destroy(removed);
       
   281         }
       
   282     }
       
   283 }
       
   284 
       
   285 DGLBuffer* DGLContext_findBuffer(DGLContext* ctx, GLuint name)
       
   286 {
       
   287     DGLES2_ASSERT(ctx != NULL);
       
   288     return (DGLBuffer*)DGLObject_find((DGLObject*)ctx->buffers, name);
       
   289 }
       
   290 
       
   291 GLboolean DGLContext_bindBuffer(DGLContext* ctx, GLuint name)
       
   292 {
       
   293     DGLES2_ASSERT(ctx != NULL);
       
   294     if(name != 0 && DGLContext_findBuffer(ctx, name) == NULL)
       
   295     {
       
   296         // A new buffer must be created.
       
   297         if(!DGLContext_createBuffer(ctx, name))
       
   298         {
       
   299             return GL_FALSE;
       
   300         }
       
   301     }
       
   302     ctx->buffer_binding = name;
       
   303 
       
   304     return GL_TRUE;
       
   305 }
       
   306 
       
   307 GLboolean DGLContext_createShader(DGLContext* ctx, GLuint name)
       
   308 {
       
   309     DGLES2_ASSERT(ctx != NULL);
       
   310     DGLES2_ASSERT(DGLContext_findShader(ctx, name) == NULL);
       
   311     DGLES2_ASSERT(name != 0);
       
   312 
       
   313     {
       
   314         DGLShader* shader = DGLShader_create(name);
       
   315         if(shader == NULL)
       
   316         {
       
   317             return GL_FALSE;
       
   318         }
       
   319         DGLObject_insert((DGLObject**)&ctx->shaders, (DGLObject*)shader);
       
   320     }
       
   321 
       
   322     return GL_TRUE;
       
   323 }
       
   324 
       
   325 void DGLContext_destroyShader(DGLContext *ctx, GLuint name)
       
   326 {
       
   327     DGLES2_ASSERT(ctx != NULL);
       
   328     if(name == 0)
       
   329     {
       
   330         return;
       
   331     }
       
   332 
       
   333     {
       
   334         DGLShader* removed = (DGLShader*)DGLObject_remove((DGLObject**)&ctx->shaders, name);
       
   335         if(removed != NULL)
       
   336         {
       
   337             DGLShader_destroy(removed);
       
   338         }
       
   339     }
       
   340 }
       
   341 
       
   342 DGLShader* DGLContext_findShader(DGLContext* ctx, GLuint name)
       
   343 {
       
   344     DGLES2_ASSERT(ctx != NULL);
       
   345     return (DGLShader*)DGLObject_find((DGLObject*)ctx->shaders, name);
       
   346 }
       
   347 
       
   348 GLboolean DGLContext_setShaderSource(DGLContext* ctx, GLuint name, const char* source, int length)
       
   349 {
       
   350     DGLES2_ASSERT(ctx != NULL);
       
   351     {
       
   352         DGLShader* shader = DGLContext_findShader(ctx, name);
       
   353         DGLES2_ASSERT(shader != NULL);
       
   354 
       
   355         // Erase the previous source.
       
   356         if(shader->source != NULL)
       
   357         {
       
   358             free(shader->source);
       
   359             shader->source = NULL;
       
   360         }
       
   361         shader->length = 0;
       
   362 
       
   363         DGLES2_ASSERT(source != NULL);
       
   364         DGLES2_ASSERT(length >= 0);
       
   365 
       
   366         shader->source = malloc(length + 1);
       
   367         if(shader->source == NULL)
       
   368         {
       
   369             return GL_FALSE;
       
   370         }
       
   371         strncpy(shader->source, source, length);
       
   372         shader->source[length] = 0;
       
   373         shader->length = length;
       
   374 
       
   375         return GL_TRUE;
       
   376     }
       
   377 }
       
   378 
       
   379 GLboolean DGLContext_createProgram(DGLContext* ctx, GLuint name)
       
   380 {
       
   381     DGLES2_ASSERT(ctx != NULL);
       
   382     DGLES2_ASSERT(DGLContext_findProgram(ctx, name) == NULL);
       
   383     DGLES2_ASSERT(name != 0);
       
   384 
       
   385     {
       
   386         DGLProgram* program = DGLProgram_create(name);
       
   387         if(program == NULL)
       
   388         {
       
   389             return GL_FALSE;
       
   390         }
       
   391         DGLObject_insert((DGLObject**)&ctx->programs, (DGLObject*)program);
       
   392     }
       
   393 
       
   394     return GL_TRUE;
       
   395 }
       
   396 
       
   397 void DGLContext_destroyProgram(DGLContext *ctx, GLuint name)
       
   398 {
       
   399     DGLES2_ASSERT(ctx != NULL);
       
   400     if(name == 0)
       
   401     {
       
   402         return;
       
   403     }
       
   404 
       
   405     {
       
   406         DGLProgram* removed = (DGLProgram*)DGLObject_remove((DGLObject**)&ctx->programs, name);
       
   407         if(removed != NULL)
       
   408         {
       
   409             DGLProgram_destroy(removed);
       
   410         }
       
   411     }
       
   412 }
       
   413 
       
   414 DGLProgram* DGLContext_findProgram(DGLContext* ctx, GLuint name)
       
   415 {
       
   416     DGLES2_ASSERT(ctx != NULL);
       
   417     return (DGLProgram*)DGLObject_find((DGLObject*)ctx->programs, name);
       
   418 }
       
   419 
       
   420 GLboolean DGLContext_createTexture(DGLContext* ctx, GLuint name, DGLTextureType type)
       
   421 {
       
   422     DGLES2_ASSERT(ctx != NULL);
       
   423     DGLES2_ASSERT(DGLContext_findTexture(ctx, name) == NULL);
       
   424 
       
   425     {
       
   426         DGLTexture* texture = DGLTexture_create(name, type, ctx->max_texture_level + 1);
       
   427         if(texture == NULL)
       
   428         {
       
   429             return GL_FALSE;
       
   430         }
       
   431         DGLObject_insert((DGLObject**)&ctx->textures, (DGLObject*)texture);
       
   432     }
       
   433 
       
   434     return GL_TRUE;
       
   435 }
       
   436 
       
   437 void DGLContext_destroyTexture(DGLContext *ctx, GLuint name)
       
   438 {
       
   439     DGLES2_ASSERT(ctx != NULL);
       
   440     if(name == 0)
       
   441     {
       
   442         // The texture named zero cannot be destroyed.
       
   443         return;
       
   444     }
       
   445 
       
   446     // Unbind texture.
       
   447     if(ctx->texture_binding_2d == name)
       
   448     {
       
   449         ctx->texture_binding_2d = 0;
       
   450     }
       
   451     if(ctx->texture_binding_cube_map == name)
       
   452     {
       
   453         ctx->texture_binding_cube_map = 0;
       
   454     }
       
   455 
       
   456     {
       
   457         DGLTexture* removed = (DGLTexture*)DGLObject_remove((DGLObject**)&ctx->textures, name);
       
   458         if(removed != NULL)
       
   459         {
       
   460             DGLTexture_destroy(removed);
       
   461         }
       
   462     }
       
   463 }
       
   464 
       
   465 DGLTexture* DGLContext_findTexture(DGLContext* ctx, GLuint name)
       
   466 {
       
   467     DGLES2_ASSERT(ctx != NULL);
       
   468     return (DGLTexture*)DGLObject_find((DGLObject*)ctx->textures, name);
       
   469 }
       
   470 
       
   471 GLboolean DGLContext_bindTexture(DGLContext* ctx, GLenum target, GLuint name)
       
   472 {
       
   473     DGLES2_ASSERT(ctx != NULL);
       
   474     if(target == GL_TEXTURE_2D)
       
   475     {
       
   476         if(DGLContext_findTexture(ctx, name) == NULL)
       
   477         {
       
   478             // A new texture must be created.
       
   479             if(!DGLContext_createTexture(ctx, name, DGLES2_TEXTURE_2D))
       
   480             {
       
   481                 return GL_FALSE;
       
   482             }
       
   483         }
       
   484         ctx->texture_binding_2d = name;
       
   485     }
       
   486     else if(target == GL_TEXTURE_CUBE_MAP)
       
   487     {
       
   488         if(DGLContext_findTexture(ctx, name) == NULL)
       
   489         {
       
   490             // A new texture must be created.
       
   491             if(!DGLContext_createTexture(ctx, name, DGLES2_TEXTURE_CUBE_MAP))
       
   492             {
       
   493                 return GL_FALSE;
       
   494             }
       
   495         }
       
   496         ctx->texture_binding_cube_map = name;
       
   497     }
       
   498     else
       
   499     {
       
   500         DGLES2_ASSERT(GL_FALSE);
       
   501     }
       
   502 
       
   503     return GL_TRUE;
       
   504 }
       
   505 
       
   506 GLuint DGLContext_getTextureBinding(const DGLContext* ctx, GLenum target)
       
   507 {
       
   508     DGLES2_ASSERT(ctx != NULL);
       
   509     switch(target)
       
   510     {
       
   511         case GL_TEXTURE_2D:
       
   512             return ctx->texture_binding_2d;
       
   513 
       
   514         case GL_TEXTURE_CUBE_MAP:
       
   515         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
       
   516         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
       
   517         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
       
   518         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
       
   519         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
       
   520         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
       
   521             return ctx->texture_binding_cube_map;
       
   522 
       
   523         default:
       
   524             DGLES2_ASSERT(GL_FALSE);
       
   525     }
       
   526 
       
   527     // No reached.
       
   528     return 0;
       
   529 }
       
   530 
       
   531 DGLTexture* DGLContext_getTexture(DGLContext* ctx, GLenum target)
       
   532 {
       
   533     DGLES2_ASSERT(ctx != NULL);
       
   534     {
       
   535         GLuint binding = DGLContext_getTextureBinding(ctx, target);
       
   536         return DGLContext_findTexture(ctx, binding);
       
   537     }
       
   538 }
       
   539 
       
   540 DGLTextureLevel* DGLContext_getTextureLevel(DGLContext* ctx, GLenum target, GLint level)
       
   541 {
       
   542     DGLES2_ASSERT(ctx != NULL);
       
   543     {
       
   544         DGLTexture* texture = DGLContext_getTexture(ctx, target);
       
   545         DGLES2_ASSERT(texture != NULL);
       
   546 
       
   547         DGLES2_ASSERT(level < ctx->max_texture_level);
       
   548         return DGLTexture_getLevel(texture, target, level);
       
   549     }
       
   550 }
       
   551 
       
   552 GLboolean DGLContext_specifyTextureFromEGLImage(DGLContext* ctx, GLeglImageOES image, GLenum target)
       
   553 {
       
   554 	DGLES2_ASSERT(ctx != NULL);
       
   555 	{
       
   556 		DGLTexture* texture;
       
   557 		GLenum internal_format;
       
   558 		GLsizei width, height;
       
   559 		GLsizei stride;
       
   560 		GLenum data_format;
       
   561 		GLenum data_type;
       
   562 		void* data;
       
   563 		GLenum error;
       
   564 
       
   565 		DGLContext_getHostError(ctx);
       
   566 
       
   567 		texture = DGLContext_getTexture(ctx, target);
       
   568 		DGLES2_ASSERT(texture != NULL);
       
   569 
       
   570 		deglGetImageInfo(image, &internal_format, &width, &height, &stride, &data_format, &data_type);
       
   571 		data = deglGetImageData(image);
       
   572 		
       
   573 		ctx->hgl.TexImage2D(target, 0, internal_format, width, height, 0, data_format, data_type, data);
       
   574 
       
   575 		error = ctx->hgl.GetError();
       
   576 		if(error == GL_NO_ERROR)
       
   577 		{
       
   578 			DGLTexture_setLevel(texture, target, 0, internal_format, width, height);
       
   579 			DGLTexture_setEGLImage(texture, target, image);
       
   580 			deglRegisterImageTarget(image, target, texture->obj.name);
       
   581 			return GL_TRUE;
       
   582 		}
       
   583 		else
       
   584 		{
       
   585 			return GL_FALSE;
       
   586 		}
       
   587 	}
       
   588 }
       
   589 
       
   590 GLboolean DGLContext_createRenderbuffer(DGLContext* ctx, GLuint name)
       
   591 {
       
   592     DGLES2_ASSERT(ctx != NULL);
       
   593     DGLES2_ASSERT(DGLContext_findRenderbuffer(ctx, name) == NULL);
       
   594     DGLES2_ASSERT(name != 0);
       
   595 
       
   596     {
       
   597         DGLRenderbuffer* buffer = DGLRenderbuffer_create(name);
       
   598         if(buffer == NULL)
       
   599         {
       
   600             return GL_FALSE;
       
   601         }
       
   602         DGLObject_insert((DGLObject**)&ctx->renderbuffers, (DGLObject*)buffer);
       
   603     }
       
   604 
       
   605     return GL_TRUE;
       
   606 }
       
   607 
       
   608 void DGLContext_destroyRenderbuffer(DGLContext *ctx, GLuint name)
       
   609 {
       
   610     DGLES2_ASSERT(ctx != NULL);
       
   611     if(name == 0)
       
   612     {
       
   613         return;
       
   614     }
       
   615 
       
   616     {
       
   617         DGLRenderbuffer* removed = (DGLRenderbuffer*)DGLObject_remove((DGLObject**)&ctx->renderbuffers, name);
       
   618         if(removed != NULL)
       
   619         {
       
   620             DGLRenderbuffer_destroy(removed);
       
   621         }
       
   622     }
       
   623 }
       
   624 
       
   625 DGLRenderbuffer* DGLContext_getColorRenderbuffer(DGLContext* ctx)
       
   626 {
       
   627 	DGLES2_ASSERT(ctx != NULL);
       
   628 	
       
   629 	if(ctx->framebuffer_binding == 0)
       
   630 	{
       
   631 		return NULL;
       
   632 	}
       
   633 
       
   634 	{
       
   635 		GLint type;
       
   636 		GLint name;
       
   637 		DGLRenderbuffer* buffer;
       
   638 
       
   639 		ctx->hgl.GetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
       
   640 
       
   641 		if(type != GL_RENDERBUFFER)
       
   642 		{
       
   643 			return NULL;
       
   644 		}
       
   645 
       
   646 		ctx->hgl.GetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &name);
       
   647 		buffer = DGLContext_findRenderbuffer(ctx, name);
       
   648 		DGLES2_ASSERT(buffer != NULL);
       
   649 		return buffer;
       
   650 	}
       
   651 }
       
   652 
       
   653 DGLRenderbuffer* DGLContext_findRenderbuffer(DGLContext* ctx, GLuint name)
       
   654 {
       
   655     DGLES2_ASSERT(ctx != NULL);
       
   656     return (DGLRenderbuffer*)DGLObject_find((DGLObject*)ctx->renderbuffers, name);
       
   657 }
       
   658 
       
   659 GLboolean DGLContext_bindRenderbuffer(DGLContext* ctx, GLuint name)
       
   660 {
       
   661     DGLES2_ASSERT(ctx != NULL);
       
   662     if(name != 0 && DGLContext_findRenderbuffer(ctx, name) == NULL)
       
   663     {
       
   664         // A new renderbuffer must be created.
       
   665         if(!DGLContext_createRenderbuffer(ctx, name))
       
   666         {
       
   667             return GL_FALSE;
       
   668         }
       
   669     }
       
   670     ctx->renderbuffer_binding = name;
       
   671 
       
   672     return GL_TRUE;
       
   673 }
       
   674 
       
   675 GLboolean DGLContext_specifyRenderbufferFromEGLImage(DGLContext* ctx, GLeglImageOES image)
       
   676 {
       
   677 	GLenum imageFormat;
       
   678 	GLenum storageFormat;
       
   679 	GLsizei width, height;
       
   680 	GLint max_renderbuffer_size;
       
   681 	GLsizei stride;
       
   682 	GLenum dataFormat;
       
   683 	GLenum dataType;
       
   684 	void* data;
       
   685 
       
   686 	deglGetImageInfo(image, &imageFormat, &width, &height, &stride, &dataFormat, &dataType);
       
   687 
       
   688 	ctx->hgl.GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size);
       
   689 	if(width > max_renderbuffer_size || width > max_renderbuffer_size)
       
   690 	{
       
   691 		return GL_FALSE;
       
   692 	}
       
   693 	
       
   694 	data = deglGetImageData(image);
       
   695 
       
   696 	// Map optimum format to available formats.
       
   697 	switch(imageFormat)
       
   698 	{
       
   699 #ifndef DGLES2_NO_SRGB
       
   700 		case GL_SRGB8:
       
   701 		case GL_SLUMINANCE8:
       
   702 #endif
       
   703 		case GL_RGB8:
       
   704 		case GL_LUMINANCE8:
       
   705 			storageFormat = GL_RGB8;
       
   706 			break;
       
   707 
       
   708 #ifndef DGLES2_NO_SRGB
       
   709 		case GL_SRGB8_ALPHA8:
       
   710 #endif
       
   711 		case GL_RGBA8:
       
   712 		case GL_ALPHA8:
       
   713 			storageFormat = GL_RGBA8;
       
   714 			break;
       
   715 			
       
   716 		default:
       
   717 			DGLES2_ASSERT(GL_FALSE);
       
   718 	}
       
   719 	
       
   720 	{
       
   721 		// Use a temporary FBO to set the renderbuffer contents.
       
   722 
       
   723 		GLint renderbuffer_binding;
       
   724 		GLint unpack_alignment;
       
   725 		GLuint fbo;
       
   726 
       
   727 		ctx->hgl.GetIntegerv(GL_RENDERBUFFER_BINDING, &renderbuffer_binding);
       
   728 		ctx->hgl.GetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment);
       
   729 
       
   730 		ctx->hgl.GenFramebuffersEXT(1, &fbo);
       
   731 		ctx->hgl.BindFramebufferEXT(GL_FRAMEBUFFER, fbo);
       
   732 		ctx->hgl.FramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer_binding);
       
   733 
       
   734 		ctx->hgl.RenderbufferStorageEXT(GL_RENDERBUFFER, storageFormat, width, height);
       
   735 		DGLES2_ASSERT(ctx->hgl.CheckFramebufferStatusEXT(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
       
   736 		ctx->hgl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
       
   737 		ctx->hgl.DrawPixels(width, height, dataFormat, dataType, data);
       
   738 
       
   739 		// Restore state.
       
   740 		ctx->hgl.PixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment);
       
   741 		ctx->hgl.BindFramebufferEXT(GL_FRAMEBUFFER, ctx->framebuffer_binding);
       
   742 		ctx->hgl.DeleteFramebuffersEXT(1, &fbo);
       
   743 	}
       
   744 
       
   745 	if(DGLContext_getHostError(ctx) == GL_NO_ERROR)
       
   746 	{
       
   747 		DGLRenderbuffer* buffer = DGLContext_findRenderbuffer(ctx, ctx->renderbuffer_binding);
       
   748 		DGLES2_ASSERT(buffer != NULL);
       
   749 		buffer->egl_image = image;
       
   750 		deglRegisterImageTarget(image, GL_RENDERBUFFER, buffer->obj.name);
       
   751 	}
       
   752 	else
       
   753 	{
       
   754 		return GL_FALSE;
       
   755 	}
       
   756 
       
   757 	return GL_TRUE;
       
   758 }
       
   759 
       
   760 void DGLContext_updateFBOAttachmentSiblings(DGLContext* ctx)
       
   761 {
       
   762 	DGLES2_ASSERT(ctx != NULL);
       
   763 
       
   764 	if(ctx->framebuffer_binding != 0)
       
   765 	{
       
   766 		GLenum type;
       
   767 		GLuint name;
       
   768 
       
   769 		ctx->hgl.GetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
       
   770 
       
   771 		if(type == GL_RENDERBUFFER)
       
   772 		{
       
   773 			DGLRenderbuffer* buffer;
       
   774 			ctx->hgl.GetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&name);
       
   775 			buffer = DGLContext_findRenderbuffer(ctx, name);
       
   776 			if(buffer != NULL && buffer->egl_image != NULL)
       
   777 			{
       
   778 				deglUpdateImageSiblings(buffer->egl_image, GL_RENDERBUFFER, buffer->obj.name);
       
   779 			}
       
   780 		}
       
   781 		else if(type == GL_TEXTURE)
       
   782 		{
       
   783 			DGLTexture* texture;
       
   784 			ctx->hgl.GetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&name);
       
   785 			texture = DGLContext_findTexture(ctx, name);
       
   786 			if(texture != NULL)
       
   787 			{
       
   788 				GLeglImageOES image;
       
   789 
       
   790 				GLenum target = GL_TEXTURE_2D;
       
   791 				if(texture->type == DGLES2_TEXTURE_CUBE_MAP)
       
   792 				{
       
   793 					ctx->hgl.GetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, (GLint*)&target);
       
   794 				}
       
   795 
       
   796 				image = DGLTexture_getEGLImage(texture, target);
       
   797 				if(image != NULL)
       
   798 				{
       
   799 					deglUpdateImageSiblings(image, target, texture->obj.name);
       
   800 				}
       
   801 			}
       
   802 		}
       
   803 	}
       
   804 }