am 8b5652be: Merge "opengles emulator: support glEGLImageTargetRenderbufferStorageOES"

* commit '8b5652be729352613bb874cef51c2556b2c00170':
  opengles emulator: support glEGLImageTargetRenderbufferStorageOES
This commit is contained in:
David Turner
2011-08-09 08:44:35 -07:00
committed by Android Git Automerger
12 changed files with 681 additions and 38 deletions

View File

@@ -308,7 +308,12 @@ bool EglDisplay:: destroyImageKHR(EGLImageKHR img) {
EGLNativeContextType EglDisplay::getGlobalSharedContext(){
android::Mutex::Autolock mutex(m_lock);
#ifndef _WIN32
return (EGLNativeContextType)m_manager[GLES_1_1]->getGlobalContext();
// find an existing OpenGL context to share with, if exist
EGLNativeContextType ret =
(EGLNativeContextType)m_manager[GLES_1_1]->getGlobalContext();
if (!ret)
ret = (EGLNativeContextType)m_manager[GLES_2_0]->getGlobalContext();
return ret;
#else
if (!m_globalSharedContext) {
//

View File

@@ -30,6 +30,7 @@
#include <GLcommon/GLDispatch.h>
#include <GLcommon/GLconversion_macros.h>
#include <GLcommon/TranslatorIfaces.h>
#include <GLcommon/FramebufferData.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <cmath>
@@ -492,9 +493,14 @@ GL_API void GL_APIENTRY glDeleteTextures( GLsizei n, const GLuint *textures) {
for(int i=0; i < n; i++){
if(textures[i] != 0)
{
TextureData* tData = getTextureData(textures[i]);
// delete the underlying OpenGL texture but only if this
// texture is not a target of EGLImage.
if (!tData || tData->sourceEGLImage == 0) {
const GLuint globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,textures[i]);
ctx->dispatcher().glDeleteTextures(1,&globalTextureName);
}
ctx->shareGroup()->deleteName(TEXTURE,textures[i]);
const GLuint globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,textures[i]);
ctx->dispatcher().glDeleteTextures(1,&globalTextureName);
if(ctx->getBindedTexture(GL_TEXTURE_2D) == textures[i])
ctx->setBindedTexture(GL_TEXTURE_2D,0);
@@ -1452,7 +1458,7 @@ GL_API void GL_APIENTRY glTexImage2D( GLenum target, GLint level, GLint interna
SET_ERROR_IF(!(GLEScmValidate::pixelOp(format,type) && internalformat == ((GLint)format)),GL_INVALID_OPERATION);
ctx->dispatcher().glTexImage2D(target,level,internalformat,width,height,border,format,type,pixels);
bool needAutoMipmap = false;
if (ctx->shareGroup().Ptr()){
TextureData *texData = getTextureTargetData(target);
@@ -1464,12 +1470,37 @@ GL_API void GL_APIENTRY glTexImage2D( GLenum target, GLint level, GLint interna
texData->internalFormat = internalformat;
texData->target = target;
if(texData->requiresAutoMipmap)
{
ctx->dispatcher().glGenerateMipmapEXT(target);
if (texData->sourceEGLImage != 0) {
//
// This texture was a target of EGLImage,
// but now it is re-defined so we need to detach
// from the EGLImage and re-generate global texture name
// for it.
//
if (texData->eglImageDetach) {
(*texData->eglImageDetach)(texData->sourceEGLImage);
}
unsigned int tex = ctx->getBindedTexture(target);
ctx->shareGroup()->replaceGlobalName(TEXTURE,
tex,
texData->oldGlobal);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, texData->oldGlobal);
texData->sourceEGLImage = 0;
texData->oldGlobal = 0;
}
needAutoMipmap = texData->requiresAutoMipmap;
}
}
ctx->dispatcher().glTexImage2D(target,level,
internalformat,width,height,
border,format,type,pixels);
if(needAutoMipmap)
{
ctx->dispatcher().glGenerateMipmapEXT(target);
}
}
static bool handleMipmapGeneration(GLenum target, GLenum pname, bool param)
@@ -1644,9 +1675,49 @@ GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOE
GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
{
GET_CTX()
//not supported by EGL
SET_ERROR_IF(false,GL_INVALID_OPERATION);
GET_CTX();
SET_ERROR_IF(target != GL_RENDERBUFFER_OES,GL_INVALID_ENUM);
EglImage *img = s_eglIface->eglAttachEGLImage((unsigned int)image);
SET_ERROR_IF(!img,GL_INVALID_VALUE);
SET_ERROR_IF(!ctx->shareGroup().Ptr(),GL_INVALID_OPERATION);
// Get current bounded renderbuffer
// raise INVALID_OPERATIOn if no renderbuffer is bounded
GLuint rb = ctx->getRenderbufferBinding();
SET_ERROR_IF(rb == 0,GL_INVALID_OPERATION);
ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb);
RenderbufferData *rbData = (RenderbufferData *)objData.Ptr();
SET_ERROR_IF(!rbData,GL_INVALID_OPERATION);
//
// flag in the renderbufferData that it is an eglImage target
//
rbData->sourceEGLImage = (unsigned int)image;
rbData->eglImageDetach = s_eglIface->eglDetachEGLImage;
rbData->eglImageGlobalTexName = img->globalTexName;
//
// if the renderbuffer is attached to a framebuffer
// change the framebuffer attachment in the undelying OpenGL
// to point to the eglImage texture object.
//
if (rbData->attachedFB) {
// update the framebuffer attachment point to the
// underlying texture of the img
GLuint prevFB = ctx->getFramebufferBinding();
if (prevFB != rbData->attachedFB) {
ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
rbData->attachedFB);
}
ctx->dispatcher().glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
rbData->attachedPoint,
GL_TEXTURE_2D,
img->globalTexName,0);
if (prevFB != rbData->attachedFB) {
ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
prevFB);
}
}
}
/* GL_OES_blend_subtract*/
@@ -1689,10 +1760,16 @@ GL_API void GLAPIENTRY glBindRenderbufferOES(GLenum target, GLuint renderbuffer)
//if buffer wasn't generated before,generate one
if(renderbuffer && ctx->shareGroup().Ptr() && !ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer)){
ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer);
ctx->shareGroup()->setObjectData(RENDERBUFFER,
renderbuffer,
ObjectDataPtr(new RenderbufferData()));
}
int globalBufferName = (renderbuffer != 0) ? ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer) : 0;
ctx->dispatcher().glBindRenderbufferEXT(target,globalBufferName);
// update renderbuffer binding state
ctx->setRenderbufferBinding(renderbuffer);
}
GL_API void GLAPIENTRY glDeleteRenderbuffersOES(GLsizei n, const GLuint *renderbuffers) {
@@ -1711,6 +1788,9 @@ GL_API void GLAPIENTRY glGenRenderbuffersOES(GLsizei n, GLuint *renderbuffers) {
if(ctx->shareGroup().Ptr()) {
for(int i=0; i<n ;i++) {
renderbuffers[i] = ctx->shareGroup()->genName(RENDERBUFFER, 0, true);
ctx->shareGroup()->setObjectData(RENDERBUFFER,
renderbuffers[i],
ObjectDataPtr(new RenderbufferData()));
}
}
}
@@ -1721,6 +1801,27 @@ GL_API void GLAPIENTRY glRenderbufferStorageOES(GLenum target, GLenum internalfo
SET_ERROR_IF(!GLEScmValidate::renderbufferTarget(target) || !GLEScmValidate::renderbufferInternalFrmt(ctx,internalformat) ,GL_INVALID_ENUM);
if (internalformat==GL_RGB565_OES) //RGB565 not supported by GL
internalformat = GL_RGB8_OES;
// Get current bounded renderbuffer
// raise INVALID_OPERATIOn if no renderbuffer is bounded
GLuint rb = ctx->getRenderbufferBinding();
SET_ERROR_IF(rb == 0,GL_INVALID_OPERATION);
ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb);
RenderbufferData *rbData = (RenderbufferData *)objData.Ptr();
SET_ERROR_IF(!rbData,GL_INVALID_OPERATION);
//
// if the renderbuffer was an eglImage target, detach from
// the eglImage.
//
if (rbData->sourceEGLImage != 0) {
if (rbData->eglImageDetach) {
(*rbData->eglImageDetach)(rbData->sourceEGLImage);
}
rbData->sourceEGLImage = 0;
rbData->eglImageGlobalTexName = 0;
}
ctx->dispatcher().glRenderbufferStorageEXT(target,internalformat,width,height);
}
@@ -1728,6 +1829,61 @@ GL_API void GLAPIENTRY glGetRenderbufferParameterivOES(GLenum target, GLenum pna
GET_CTX()
SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION);
SET_ERROR_IF(!GLEScmValidate::renderbufferTarget(target) || !GLEScmValidate::renderbufferParams(pname) ,GL_INVALID_ENUM);
//
// If this is a renderbuffer which is eglimage's target, we
// should query the underlying eglimage's texture object instead.
//
GLuint rb = ctx->getRenderbufferBinding();
if (rb) {
ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb);
RenderbufferData *rbData = (RenderbufferData *)objData.Ptr();
if (rbData && rbData->sourceEGLImage != 0) {
GLenum texPname;
switch(pname) {
case GL_RENDERBUFFER_WIDTH_OES:
texPname = GL_TEXTURE_WIDTH;
break;
case GL_RENDERBUFFER_HEIGHT_OES:
texPname = GL_TEXTURE_HEIGHT;
break;
case GL_RENDERBUFFER_INTERNAL_FORMAT_OES:
texPname = GL_TEXTURE_INTERNAL_FORMAT;
break;
case GL_RENDERBUFFER_RED_SIZE_OES:
texPname = GL_TEXTURE_RED_SIZE;
break;
case GL_RENDERBUFFER_GREEN_SIZE_OES:
texPname = GL_TEXTURE_GREEN_SIZE;
break;
case GL_RENDERBUFFER_BLUE_SIZE_OES:
texPname = GL_TEXTURE_BLUE_SIZE;
break;
case GL_RENDERBUFFER_ALPHA_SIZE_OES:
texPname = GL_TEXTURE_ALPHA_SIZE;
break;
case GL_RENDERBUFFER_DEPTH_SIZE_OES:
texPname = GL_TEXTURE_DEPTH_SIZE;
break;
case GL_RENDERBUFFER_STENCIL_SIZE_OES:
default:
*params = 0; //XXX
return;
break;
}
GLint prevTex;
ctx->dispatcher().glGetIntegerv(GL_TEXTURE_BINDING_2D, &prevTex);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D,
rbData->eglImageGlobalTexName);
ctx->dispatcher().glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
texPname,
params);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, prevTex);
return;
}
}
ctx->dispatcher().glGetRenderbufferParameterivEXT(target,pname,params);
}
@@ -1746,9 +1902,14 @@ GL_API void GLAPIENTRY glBindFramebufferOES(GLenum target, GLuint framebuffer) {
SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) ,GL_INVALID_ENUM);
if (framebuffer && ctx->shareGroup().Ptr() && !ctx->shareGroup()->isObject(FRAMEBUFFER,framebuffer)) {
ctx->shareGroup()->genName(FRAMEBUFFER,framebuffer);
ctx->shareGroup()->setObjectData(FRAMEBUFFER, framebuffer,
ObjectDataPtr(new FramebufferData(framebuffer)));
}
int globalBufferName = (framebuffer!=0) ? ctx->shareGroup()->getGlobalName(FRAMEBUFFER,framebuffer) : 0;
ctx->dispatcher().glBindFramebufferEXT(target,globalBufferName);
// update framebuffer binding state
ctx->setFramebufferBinding(framebuffer);
}
GL_API void GLAPIENTRY glDeleteFramebuffersOES(GLsizei n, const GLuint *framebuffers) {
@@ -1767,6 +1928,8 @@ GL_API void GLAPIENTRY glGenFramebuffersOES(GLsizei n, GLuint *framebuffers) {
if (ctx->shareGroup().Ptr()) {
for (int i=0;i<n;i++) {
framebuffers[i] = ctx->shareGroup()->genName(FRAMEBUFFER, 0, true);
ctx->shareGroup()->setObjectData(FRAMEBUFFER, framebuffers[i],
ObjectDataPtr(new FramebufferData(framebuffers[i])));
}
}
}
@@ -1783,22 +1946,79 @@ GL_API void GLAPIENTRY glFramebufferTexture2DOES(GLenum target, GLenum attachmen
SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION);
SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) || !GLEScmValidate::framebufferAttachment(attachment) ||
!GLEScmValidate::textureTargetEx(textarget),GL_INVALID_ENUM);
if (ctx->shareGroup().Ptr() && !ctx->shareGroup()->isObject(TEXTURE,texture)) {
ctx->shareGroup()->genName(TEXTURE,texture);
SET_ERROR_IF(!ctx->shareGroup().Ptr(), GL_INVALID_OPERATION);
GLuint globalTexName = 0;
if(texture) {
if (!ctx->shareGroup()->isObject(TEXTURE,texture)) {
ctx->shareGroup()->genName(TEXTURE,texture);
}
ObjectLocalName texname = TextureLocalName(textarget,texture);
globalTexName = ctx->shareGroup()->getGlobalName(TEXTURE,texname);
}
GLuint globalTexName = ctx->shareGroup()->getGlobalName(TEXTURE,texture);
ctx->dispatcher().glFramebufferTexture2DEXT(target,attachment,textarget,globalTexName,level);
// Update the the current framebuffer object attachment state
GLuint fbName = ctx->getFramebufferBinding();
ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName);
if (fbObj.Ptr() != NULL) {
FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
fbData->setAttachment(attachment, textarget,
texture, ObjectDataPtr(NULL));
}
}
GL_API void GLAPIENTRY glFramebufferRenderbufferOES(GLenum target, GLenum attachment,GLenum renderbuffertarget, GLuint renderbuffer) {
GET_CTX()
SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION);
SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) || !GLEScmValidate::framebufferAttachment(attachment) ||
SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) ||
!GLEScmValidate::framebufferAttachment(attachment) ||
!GLEScmValidate::renderbufferTarget(renderbuffertarget), GL_INVALID_ENUM);
if (ctx->shareGroup().Ptr() && !ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer)) {
ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer);
SET_ERROR_IF(!ctx->shareGroup().Ptr(), GL_INVALID_OPERATION);
GLuint globalBufferName = 0;
ObjectDataPtr obj;
// generate the renderbuffer object if not yet exist
if (renderbuffer) {
if (!ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer)) {
ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer);
obj = ObjectDataPtr(new RenderbufferData());
ctx->shareGroup()->setObjectData(RENDERBUFFER,
renderbuffer,
ObjectDataPtr(new RenderbufferData()));
}
else {
obj = ctx->shareGroup()->getObjectData(RENDERBUFFER,renderbuffer);
}
globalBufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer);
}
GLuint globalBufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer);
// Update the the current framebuffer object attachment state
GLuint fbName = ctx->getFramebufferBinding();
ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName);
if (fbObj.Ptr() != NULL) {
FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
fbData->setAttachment(attachment, renderbuffertarget, renderbuffer, obj);
}
if (renderbuffer && obj.Ptr() != NULL) {
RenderbufferData *rbData = (RenderbufferData *)obj.Ptr();
if (rbData->sourceEGLImage != 0) {
//
// This renderbuffer object is an eglImage target
// attach the eglimage's texture instead the renderbuffer.
//
ctx->dispatcher().glFramebufferTexture2DEXT(target,
attachment,
GL_TEXTURE_2D,
rbData->eglImageGlobalTexName,0);
return;
}
}
ctx->dispatcher().glFramebufferRenderbufferEXT(target,attachment,renderbuffertarget,globalBufferName);
}
@@ -1807,6 +2027,28 @@ GL_API void GLAPIENTRY glGetFramebufferAttachmentParameterivOES(GLenum target, G
SET_ERROR_IF(!ctx->getCaps()->GL_EXT_FRAMEBUFFER_OBJECT,GL_INVALID_OPERATION);
SET_ERROR_IF(!GLEScmValidate::framebufferTarget(target) || !GLEScmValidate::framebufferAttachment(attachment) ||
!GLEScmValidate::framebufferAttachmentParams(pname), GL_INVALID_ENUM);
//
// Take the attachment attribute from our state - if available
//
GLuint fbName = ctx->getFramebufferBinding();
if (fbName) {
ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName);
if (fbObj.Ptr() != NULL) {
FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
GLenum target;
GLuint name = fbData->getAttachment(attachment, &target, NULL);
if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES) {
*params = target;
return;
}
else if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES) {
*params = name;
return;
}
}
}
ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(target,attachment,pname,params);
}

View File

@@ -31,6 +31,7 @@
#include "ShaderParser.h"
#include "ProgramData.h"
#include <GLcommon/TextureUtils.h>
#include <GLcommon/FramebufferData.h>
extern "C" {
@@ -202,10 +203,15 @@ GL_APICALL void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer
//if framebuffer wasn't generated before,generate one
if(!globalFrameBufferName){
ctx->shareGroup()->genName(FRAMEBUFFER,framebuffer);
ctx->shareGroup()->setObjectData(FRAMEBUFFER, framebuffer,
ObjectDataPtr(new FramebufferData(framebuffer)));
globalFrameBufferName = ctx->shareGroup()->getGlobalName(FRAMEBUFFER,framebuffer);
}
}
ctx->dispatcher().glBindFramebufferEXT(target,globalFrameBufferName);
// update framebuffer binding state
ctx->setFramebufferBinding(framebuffer);
}
GL_APICALL void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer){
@@ -218,10 +224,16 @@ GL_APICALL void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuff
//if renderbuffer wasn't generated before,generate one
if(!globalRenderBufferName){
ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer);
ctx->shareGroup()->setObjectData(RENDERBUFFER,
renderbuffer,
ObjectDataPtr(new RenderbufferData()));
globalRenderBufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer);
}
}
ctx->dispatcher().glBindRenderbufferEXT(target,globalRenderBufferName);
// update renderbuffer binding state
ctx->setRenderbufferBinding(renderbuffer);
}
GL_APICALL void GL_APIENTRY glBindTexture(GLenum target, GLuint texture){
@@ -439,9 +451,14 @@ GL_APICALL void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)
if(ctx->shareGroup().Ptr()) {
for(int i=0; i < n; i++){
if (textures[i]!=0) {
const GLuint globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,textures[i]);
TextureData* tData = getTextureData(textures[i]);
// delete the underlying OpenGL texture but only if this
// texture is not a target of EGLImage.
if (!tData || tData->sourceEGLImage == 0) {
const GLuint globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,textures[i]);
ctx->dispatcher().glDeleteTextures(1,&globalTextureName);
}
ctx->shareGroup()->deleteName(TEXTURE,textures[i]);
ctx->dispatcher().glDeleteTextures(1,&globalTextureName);
if (ctx->getBindedTexture(GL_TEXTURE_2D) == textures[i])
ctx->setBindedTexture(GL_TEXTURE_2D,0);
@@ -597,12 +614,50 @@ GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum att
SET_ERROR_IF(!(GLESv2Validate::framebufferTarget(target) &&
GLESv2Validate::renderbufferTarget(renderbuffertarget) &&
GLESv2Validate::framebufferAttachment(attachment)),GL_INVALID_ENUM);
SET_ERROR_IF(!ctx->shareGroup().Ptr(), GL_INVALID_OPERATION);
if(ctx->shareGroup().Ptr()) {
GLuint globalRenderbufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer);
ctx->dispatcher().glFramebufferRenderbufferEXT(target,attachment,renderbuffertarget,globalRenderbufferName);
GLuint globalRenderbufferName = 0;
ObjectDataPtr obj;
// generate the renderbuffer object if not yet exist
if(renderbuffer) {
if (!ctx->shareGroup()->isObject(RENDERBUFFER,renderbuffer)) {
ctx->shareGroup()->genName(RENDERBUFFER,renderbuffer);
obj = ObjectDataPtr(new RenderbufferData());
ctx->shareGroup()->setObjectData(RENDERBUFFER,
renderbuffer, obj);
}
else {
obj = ctx->shareGroup()->getObjectData(RENDERBUFFER, renderbuffer);
}
globalRenderbufferName = ctx->shareGroup()->getGlobalName(RENDERBUFFER,renderbuffer);
}
// Update the the current framebuffer object attachment state
GLuint fbName = ctx->getFramebufferBinding();
ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName);
if (fbObj.Ptr() != NULL) {
FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
fbData->setAttachment(attachment, renderbuffertarget, renderbuffer, obj);
}
if (renderbuffer && obj.Ptr() != NULL) {
RenderbufferData *rbData = (RenderbufferData *)obj.Ptr();
if (rbData->sourceEGLImage != 0) {
//
// This renderbuffer object is an eglImage target
// attach the eglimage's texture instead the renderbuffer.
//
ctx->dispatcher().glFramebufferTexture2DEXT(target,
attachment,
GL_TEXTURE_2D,
rbData->eglImageGlobalTexName,0);
return;
}
}
ctx->dispatcher().glFramebufferRenderbufferEXT(target,attachment,renderbuffertarget,globalRenderbufferName);
}
GL_APICALL void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level){
@@ -611,19 +666,27 @@ GL_APICALL void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attach
GLESv2Validate::textureTargetEx(textarget) &&
GLESv2Validate::framebufferAttachment(attachment)),GL_INVALID_ENUM);
SET_ERROR_IF(level != 0, GL_INVALID_VALUE);
SET_ERROR_IF(!ctx->shareGroup().Ptr(), GL_INVALID_OPERATION);
if(texture == 0)
{
// Special case - detach texture
ctx->dispatcher().glFramebufferTexture2DEXT(target,attachment,textarget,0,level);
}
else
{
if(ctx->shareGroup().Ptr()) {
ObjectLocalName texname = TextureLocalName(textarget,texture);
GLuint globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,texname);
ctx->dispatcher().glFramebufferTexture2DEXT(target,attachment,textarget,globalTextureName,level);
GLuint globalTextureName = 0;
if(texture) {
if (!ctx->shareGroup()->isObject(TEXTURE,texture)) {
ctx->shareGroup()->genName(TEXTURE,texture);
}
ObjectLocalName texname = TextureLocalName(textarget,texture);
globalTextureName = ctx->shareGroup()->getGlobalName(TEXTURE,texname);
}
ctx->dispatcher().glFramebufferTexture2DEXT(target,attachment,textarget,globalTextureName,level);
// Update the the current framebuffer object attachment state
GLuint fbName = ctx->getFramebufferBinding();
ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName);
if (fbObj.Ptr() != NULL) {
FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
fbData->setAttachment(attachment, textarget,
texture, ObjectDataPtr(NULL));
}
}
@@ -657,6 +720,8 @@ GL_APICALL void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers){
if(ctx->shareGroup().Ptr()) {
for(int i=0; i<n ;i++) {
framebuffers[i] = ctx->shareGroup()->genName(FRAMEBUFFER, 0 ,true);
ctx->shareGroup()->setObjectData(FRAMEBUFFER, framebuffers[i],
ObjectDataPtr(new FramebufferData(framebuffers[i])));
}
}
}
@@ -667,6 +732,9 @@ GL_APICALL void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers
if(ctx->shareGroup().Ptr()) {
for(int i=0; i<n ;i++) {
renderbuffers[i] = ctx->shareGroup()->genName(RENDERBUFFER, 0, true);
ctx->shareGroup()->setObjectData(RENDERBUFFER,
renderbuffers[i],
ObjectDataPtr(new RenderbufferData()));
}
}
}
@@ -927,12 +995,95 @@ GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target
SET_ERROR_IF(!(GLESv2Validate::framebufferTarget(target) &&
GLESv2Validate::framebufferAttachment(attachment) &&
GLESv2Validate::framebufferAttachmentParams(pname)),GL_INVALID_ENUM);
//
// Take the attachment attribute from our state - if available
//
GLuint fbName = ctx->getFramebufferBinding();
if (fbName) {
ObjectDataPtr fbObj = ctx->shareGroup()->getObjectData(FRAMEBUFFER,fbName);
if (fbObj.Ptr() != NULL) {
FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
GLenum target;
GLuint name = fbData->getAttachment(attachment, &target, NULL);
if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) {
if (target == GL_TEXTURE_2D) {
*params = GL_TEXTURE;
return;
}
else if (target == GL_RENDERBUFFER) {
*params = GL_RENDERBUFFER;
return;
}
}
else if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
*params = name;
return;
}
}
}
ctx->dispatcher().glGetFramebufferAttachmentParameterivEXT(target,attachment,pname,params);
}
GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params){
GET_CTX();
SET_ERROR_IF(!(GLESv2Validate::renderbufferTarget(target) && GLESv2Validate::renderbufferParams(pname)),GL_INVALID_ENUM);
//
// If this is a renderbuffer which is eglimage's target, we
// should query the underlying eglimage's texture object instead.
//
GLuint rb = ctx->getRenderbufferBinding();
if (rb) {
ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb);
RenderbufferData *rbData = (RenderbufferData *)objData.Ptr();
if (rbData && rbData->sourceEGLImage != 0) {
GLenum texPname;
switch(pname) {
case GL_RENDERBUFFER_WIDTH:
texPname = GL_TEXTURE_WIDTH;
break;
case GL_RENDERBUFFER_HEIGHT:
texPname = GL_TEXTURE_HEIGHT;
break;
case GL_RENDERBUFFER_INTERNAL_FORMAT:
texPname = GL_TEXTURE_INTERNAL_FORMAT;
break;
case GL_RENDERBUFFER_RED_SIZE:
texPname = GL_TEXTURE_RED_SIZE;
break;
case GL_RENDERBUFFER_GREEN_SIZE:
texPname = GL_TEXTURE_GREEN_SIZE;
break;
case GL_RENDERBUFFER_BLUE_SIZE:
texPname = GL_TEXTURE_BLUE_SIZE;
break;
case GL_RENDERBUFFER_ALPHA_SIZE:
texPname = GL_TEXTURE_ALPHA_SIZE;
break;
case GL_RENDERBUFFER_DEPTH_SIZE:
texPname = GL_TEXTURE_DEPTH_SIZE;
break;
case GL_RENDERBUFFER_STENCIL_SIZE:
default:
*params = 0; //XXX
return;
break;
}
GLint prevTex;
ctx->dispatcher().glGetIntegerv(GL_TEXTURE_BINDING_2D, &prevTex);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D,
rbData->eglImageGlobalTexName);
ctx->dispatcher().glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
texPname,
params);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, prevTex);
return;
}
}
ctx->dispatcher().glGetRenderbufferParameterivEXT(target,pname,params);
}
@@ -1338,6 +1489,27 @@ GL_APICALL void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum interna
internal = internalformat;
break;
}
// Get current bounded renderbuffer
// raise INVALID_OPERATIOn if no renderbuffer is bounded
GLuint rb = ctx->getRenderbufferBinding();
SET_ERROR_IF(rb == 0,GL_INVALID_OPERATION);
ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb);
RenderbufferData *rbData = (RenderbufferData *)objData.Ptr();
SET_ERROR_IF(!rbData,GL_INVALID_OPERATION);
//
// if the renderbuffer was an eglImage target, detach from
// the eglImage.
//
if (rbData->sourceEGLImage != 0) {
if (rbData->eglImageDetach) {
(*rbData->eglImageDetach)(rbData->sourceEGLImage);
}
rbData->sourceEGLImage = 0;
rbData->eglImageGlobalTexName = 0;
}
ctx->dispatcher().glRenderbufferStorageEXT(target,internal,width,height);
}
@@ -1432,8 +1604,28 @@ GL_APICALL void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint inte
texData->border = border;
texData->internalFormat = internalformat;
texData->target = target;
if (texData->sourceEGLImage != 0) {
//
// This texture was a target of EGLImage,
// but now it is re-defined so we need to detach
// from the EGLImage and re-generate global texture name
// for it.
//
if (texData->eglImageDetach) {
(*texData->eglImageDetach)(texData->sourceEGLImage);
}
unsigned int tex = ctx->getBindedTexture(target);
ctx->shareGroup()->replaceGlobalName(TEXTURE,
tex,
texData->oldGlobal);
ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, texData->oldGlobal);
texData->sourceEGLImage = 0;
texData->oldGlobal = 0;
}
}
}
if (type==GL_HALF_FLOAT_OES)
type = GL_HALF_FLOAT_NV;
if (pixels==NULL && type==GL_UNSIGNED_SHORT_5_5_5_1)
@@ -1658,13 +1850,54 @@ GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglIma
SET_ERROR_IF(texData==NULL,GL_INVALID_OPERATION);
texData->sourceEGLImage = (unsigned int)image;
texData->eglImageDetach = s_eglIface->eglDetachEGLImage;
texData->oldGlobal = oldGlobal;
}
}
}
GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
{
GET_CTX()
//not supported by EGL
SET_ERROR_IF(false,GL_INVALID_OPERATION);
GET_CTX();
SET_ERROR_IF(target != GL_RENDERBUFFER_OES,GL_INVALID_ENUM);
EglImage *img = s_eglIface->eglAttachEGLImage((unsigned int)image);
SET_ERROR_IF(!img,GL_INVALID_VALUE);
SET_ERROR_IF(!ctx->shareGroup().Ptr(),GL_INVALID_OPERATION);
// Get current bounded renderbuffer
// raise INVALID_OPERATIOn if no renderbuffer is bounded
GLuint rb = ctx->getRenderbufferBinding();
SET_ERROR_IF(rb == 0,GL_INVALID_OPERATION);
ObjectDataPtr objData = ctx->shareGroup()->getObjectData(RENDERBUFFER,rb);
RenderbufferData *rbData = (RenderbufferData *)objData.Ptr();
SET_ERROR_IF(!rbData,GL_INVALID_OPERATION);
//
// flag in the renderbufferData that it is an eglImage target
//
rbData->sourceEGLImage = (unsigned int)image;
rbData->eglImageDetach = s_eglIface->eglDetachEGLImage;
rbData->eglImageGlobalTexName = img->globalTexName;
//
// if the renderbuffer is attached to a framebuffer
// change the framebuffer attachment in the undelying OpenGL
// to point to the eglImage texture object.
//
if (rbData->attachedFB) {
// update the framebuffer attachment point to the
// underlying texture of the img
GLuint prevFB = ctx->getFramebufferBinding();
if (prevFB != rbData->attachedFB) {
ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
rbData->attachedFB);
}
ctx->dispatcher().glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
rbData->attachedPoint,
GL_TEXTURE_2D,
img->globalTexName,0);
if (prevFB != rbData->attachedFB) {
ctx->dispatcher().glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
prevFB);
}
}
}

View File

@@ -56,6 +56,7 @@
const GLubyte * GLAPIENTRY dummy_glGetString(GLenum name){ return 0;}
void GLAPIENTRY dummy_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params){}
void GLAPIENTRY dummy_glGetTexParameteriv(GLenum target, GLenum pname, GLint *params){}
void GLAPIENTRY dummy_glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params){}
void GLAPIENTRY dummy_glHint(GLenum target, GLenum mode){}
GLboolean GLAPIENTRY dummy_glIsBuffer(GLuint){ return false;}
GLboolean GLAPIENTRY dummy_glIsEnabled(GLenum cap){ return false;}

View File

@@ -63,6 +63,7 @@
const GLubyte * GLAPIENTRY dummy_glGetString(GLenum name);
void GLAPIENTRY dummy_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
void GLAPIENTRY dummy_glGetTexParameteriv(GLenum target, GLenum pname, GLint *params);
void GLAPIENTRY dummy_glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
void GLAPIENTRY dummy_glHint(GLenum target, GLenum mode);
GLboolean GLAPIENTRY dummy_glIsBuffer(GLuint);
GLboolean GLAPIENTRY dummy_glIsEnabled(GLenum cap);

View File

@@ -108,6 +108,7 @@ void (GLAPIENTRY *GLDispatch::glGetIntegerv)(GLenum,GLint *) = NULL;
const GLubyte * (GLAPIENTRY *GLDispatch::glGetString) (GLenum) = NULL;
void (GLAPIENTRY *GLDispatch::glGetTexParameterfv)(GLenum,GLenum,GLfloat *) = NULL;
void (GLAPIENTRY *GLDispatch::glGetTexParameteriv)(GLenum,GLenum,GLint *) = NULL;
void (GLAPIENTRY *GLDispatch::glGetTexLevelParameteriv) (GLenum target, GLint level, GLenum pname, GLint *params) = NULL;
void (GLAPIENTRY *GLDispatch::glHint)(GLenum,GLenum) = NULL;
GLboolean (GLAPIENTRY *GLDispatch::glIsBuffer)(GLuint) = NULL;
GLboolean (GLAPIENTRY *GLDispatch::glIsEnabled)(GLenum) = NULL;
@@ -345,6 +346,7 @@ void GLDispatch::dispatchFuncs(GLESVersion version){
LOAD_GL_FUNC(glTexParameterfv);
LOAD_GL_FUNC(glGetTexParameterfv);
LOAD_GL_FUNC(glGetTexParameteriv);
LOAD_GL_FUNC(glGetTexLevelParameteriv);
LOAD_GL_FUNC(glHint);
LOAD_GL_FUNC(glIsBuffer);
LOAD_GL_FUNC(glIsEnabled);

View File

@@ -5,6 +5,7 @@
#include <GLES/glext.h>
#include <GLcommon/GLESvalidate.h>
#include <GLcommon/TextureUtils.h>
#include <strings.h>
//decleration
static int findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices);
@@ -139,7 +140,11 @@ GLEScontext::GLEScontext():
m_glError(GL_NO_ERROR) ,
m_texState(0) ,
m_arrayBuffer(0) ,
m_elementBuffer(0){};
m_elementBuffer(0),
m_renderbuffer(0),
m_framebuffer(0)
{
};
GLenum GLEScontext::getGLerror() {
return m_glError;

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _FRAMEBUFFER_DATA_H
#define _FRAMEBUFFER_DATA_H
#include "objectNameManager.h"
#include <GLES/gl.h>
#include <GLES/glext.h>
class RenderbufferData : public ObjectData
{
public:
RenderbufferData() : sourceEGLImage(0),
eglImageDetach(NULL),
attachedFB(0),
attachedPoint(0),
eglImageGlobalTexName(0)
{}
~RenderbufferData() {
if (sourceEGLImage && eglImageDetach) (*eglImageDetach)(sourceEGLImage);
}
unsigned int sourceEGLImage;
void (*eglImageDetach)(unsigned int imageId);
GLuint attachedFB;
GLenum attachedPoint;
GLuint eglImageGlobalTexName;
};
const int MAX_ATTACH_POINTS = 3;
class FramebufferData : public ObjectData
{
public:
explicit FramebufferData(GLuint name) {
m_fbName = name;
for (int i=0; i<MAX_ATTACH_POINTS; i++) {
m_attachPoints[i].target = 0;
m_attachPoints[i].name = 0;
m_attachPoints[i].obj = ObjectDataPtr(NULL);
}
}
~FramebufferData() {
for (int i=0; i<MAX_ATTACH_POINTS; i++) {
detachObject(i);
}
}
void setAttachment(GLenum attachment,
GLenum target,
GLuint name,
ObjectDataPtr obj) {
int idx = attachmentPointIndex(attachment);
if (m_attachPoints[idx].target != target ||
m_attachPoints[idx].name != name ||
m_attachPoints[idx].obj.Ptr() != obj.Ptr()) {
detachObject(idx);
m_attachPoints[idx].target = target;
m_attachPoints[idx].name = name;
m_attachPoints[idx].obj = obj;
if (target == GL_RENDERBUFFER_OES &&
obj.Ptr() != NULL) {
RenderbufferData *rbData = (RenderbufferData *)obj.Ptr();
rbData->attachedFB = m_fbName;
rbData->attachedPoint = attachment;
}
}
}
GLuint getAttachment(GLenum attachment,
GLenum *outTarget,
ObjectDataPtr *outObj) {
int idx = attachmentPointIndex(attachment);
if (outTarget) *outTarget = m_attachPoints[idx].target;
if (outObj) *outObj = m_attachPoints[idx].obj;
return m_attachPoints[idx].name;
}
private:
inline int attachmentPointIndex(GLenum attachment)
{
switch(attachment) {
case GL_COLOR_ATTACHMENT0_OES:
return 0;
case GL_DEPTH_ATTACHMENT_OES:
return 1;
case GL_STENCIL_ATTACHMENT_OES:
return 3;
default:
return MAX_ATTACH_POINTS;
}
}
void detachObject(int idx) {
if (m_attachPoints[idx].target == GL_RENDERBUFFER_OES &&
m_attachPoints[idx].obj.Ptr() != NULL) {
RenderbufferData *rbData = (RenderbufferData *)m_attachPoints[idx].obj.Ptr();
rbData->attachedFB = 0;
rbData->attachedPoint = 0;
}
m_attachPoints[idx].target = 0;
m_attachPoints[idx].name = 0;
m_attachPoints[idx].obj = ObjectDataPtr(NULL);
}
private:
GLuint m_fbName;
struct attachPoint {
GLenum target;
GLuint name;
ObjectDataPtr obj;
} m_attachPoints[MAX_ATTACH_POINTS+1];
};
#endif

View File

@@ -73,6 +73,7 @@ public:
static const GLubyte * (GLAPIENTRY *glGetString) (GLenum name);
static void (GLAPIENTRY *glGetTexParameterfv) (GLenum target, GLenum pname, GLfloat *params);
static void (GLAPIENTRY *glGetTexParameteriv) (GLenum target, GLenum pname, GLint *params);
static void (GLAPIENTRY *glGetTexLevelParameteriv) (GLenum target, GLint level, GLenum pname, GLint *params);
static void (GLAPIENTRY *glHint) (GLenum target, GLenum mode);
static GLboolean (GLAPIENTRY *glIsBuffer) (GLuint);
static GLboolean (GLAPIENTRY *glIsEnabled) (GLenum cap);

View File

@@ -136,6 +136,11 @@ public:
virtual ~GLEScontext();
virtual int getMaxTexUnits() = 0;
void setRenderbufferBinding(GLuint rb) { m_renderbuffer = rb; }
GLuint getRenderbufferBinding() const { return m_renderbuffer; }
void setFramebufferBinding(GLuint fb) { m_framebuffer = fb; }
GLuint getFramebufferBinding() const { return m_framebuffer; }
static GLDispatch& dispatcher(){return s_glDispatch;};
static int getMaxLights(){return s_glSupport.maxLights;}
@@ -177,6 +182,8 @@ private:
textureUnitState* m_texState;
unsigned int m_arrayBuffer;
unsigned int m_elementBuffer;
GLuint m_renderbuffer;
GLuint m_framebuffer;
};
#endif

View File

@@ -45,7 +45,8 @@ public:
sourceEGLImage(0),
wasBound(false),
requiresAutoMipmap(false),
target(0) {
target(0),
oldGlobal(0) {
memset(crop_rect,0,4*sizeof(int));
};
@@ -59,6 +60,7 @@ public:
int crop_rect[4];
void (*eglImageDetach)(unsigned int imageId);
GLenum target;
GLuint oldGlobal;
};
struct EglImage

View File

@@ -31,3 +31,12 @@ typedef double GLdouble; /* double precision float */
#define GL_HALF_FLOAT 0x140B
#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
#define GL_POINT_SPRITE 0x8861
#define GL_FRAMEBUFFER_EXT 0x8D40
#define GL_TEXTURE_WIDTH 0x1000
#define GL_TEXTURE_HEIGHT 0x1001
#define GL_TEXTURE_RED_SIZE 0x805C
#define GL_TEXTURE_GREEN_SIZE 0x805D
#define GL_TEXTURE_BLUE_SIZE 0x805E
#define GL_TEXTURE_ALPHA_SIZE 0x805F
#define GL_TEXTURE_DEPTH_SIZE 0x884A
#define GL_TEXTURE_INTERNAL_FORMAT 0x1003