Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
=================================================================== |
--- gpu/command_buffer/service/gles2_cmd_decoder.cc (revision 111321) |
+++ gpu/command_buffer/service/gles2_cmd_decoder.cc (working copy) |
@@ -15,6 +15,9 @@ |
#include "base/atomicops.h" |
#include "base/at_exit.h" |
#include "base/bind.h" |
+#if defined(OS_MACOSX) |
+#include "base/mac/scoped_cftyperef.h" |
+#endif |
#include "base/memory/scoped_ptr.h" |
#include "base/memory/weak_ptr.h" |
#include "build/build_config.h" |
@@ -41,6 +44,9 @@ |
#include "ui/gfx/gl/gl_context.h" |
#include "ui/gfx/gl/gl_implementation.h" |
#include "ui/gfx/gl/gl_surface.h" |
+#if defined(OS_MACOSX) |
+#include "ui/gfx/surface/io_surface_support_mac.h" |
+#endif |
#if !defined(GL_DEPTH24_STENCIL8) |
#define GL_DEPTH24_STENCIL8 0x88F0 |
@@ -560,12 +566,26 @@ |
// glBindTexture |
TextureManager::TextureInfo::Ref bound_texture_external_oes; |
+ // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with |
+ // glBindTexture |
+ TextureManager::TextureInfo::Ref bound_texture_rectangle_arb; |
+ |
TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) { |
DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || |
- type == GL_SAMPLER_EXTERNAL_OES); |
- return type == GL_SAMPLER_2D ? bound_texture_2d : |
- (type == GL_SAMPLER_EXTERNAL_OES ? bound_texture_external_oes : |
- bound_texture_cube_map); |
+ type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB); |
+ switch (type) { |
+ case GL_SAMPLER_2D: |
+ return bound_texture_2d; |
+ case GL_SAMPLER_CUBE: |
+ return bound_texture_cube_map; |
+ case GL_SAMPLER_EXTERNAL_OES: |
+ return bound_texture_external_oes; |
+ case GL_SAMPLER_2D_RECT_ARB: |
+ return bound_texture_rectangle_arb; |
+ } |
+ |
+ NOTREACHED(); |
+ return NULL; |
} |
void Unbind(TextureManager::TextureInfo* texture) { |
@@ -723,6 +743,14 @@ |
GLenum type, |
const void * data); |
+ // Wrapper for TexImageIOSurface2DCHROMIUM. |
+ void DoTexImageIOSurface2DCHROMIUM( |
+ GLenum target, |
+ GLsizei width, |
+ GLsizei height, |
+ GLuint io_surface_id, |
+ GLuint plane); |
+ |
// Creates a ProgramInfo for the given program. |
ProgramManager::ProgramInfo* CreateProgramInfo( |
GLuint client_id, GLuint service_id) { |
@@ -1181,10 +1209,9 @@ |
case GL_TEXTURE_EXTERNAL_OES: |
info = unit.bound_texture_external_oes; |
break; |
- // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to |
- // track |texture_| with the currently bound TEXTURE_RECTANGLE texture, |
- // because |texture_| is used by the FBO rendering mechanism for readback |
- // to the bits that get sent to the browser. |
+ case GL_TEXTURE_RECTANGLE_ARB: |
+ info = unit.bound_texture_rectangle_arb; |
+ break; |
default: |
NOTREACHED(); |
return NULL; |
@@ -1194,10 +1221,20 @@ |
GLenum GetBindTargetForSamplerType(GLenum type) { |
DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || |
- type == GL_SAMPLER_EXTERNAL_OES); |
- return type == GL_SAMPLER_2D ? GL_TEXTURE_2D : |
- (type == GL_SAMPLER_EXTERNAL_OES ? GL_TEXTURE_EXTERNAL_OES : |
- GL_TEXTURE_CUBE_MAP); |
+ type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB); |
+ switch (type) { |
+ case GL_SAMPLER_2D: |
+ return GL_TEXTURE_2D; |
+ case GL_SAMPLER_CUBE: |
+ return GL_TEXTURE_CUBE_MAP; |
+ case GL_SAMPLER_EXTERNAL_OES: |
+ return GL_TEXTURE_EXTERNAL_OES; |
+ case GL_SAMPLER_2D_RECT_ARB: |
+ return GL_TEXTURE_RECTANGLE_ARB; |
+ } |
+ |
+ NOTREACHED(); |
+ return 0; |
} |
// Gets the framebuffer info for a particular target. |
@@ -1245,6 +1282,10 @@ |
// Returns true if the context was just lost due to e.g. GL_ARB_robustness. |
bool WasContextLost(); |
+#if defined(OS_MACOSX) |
+ void ReleaseIOSurfaceForTexture(GLuint texture_id); |
+#endif |
+ |
// Generate a member function prototype for each command in an automated and |
// typesafe way. |
#define GLES2_CMD_OP(name) \ |
@@ -1422,6 +1463,11 @@ |
bool force_webgl_glsl_validation_; |
bool derivatives_explicitly_enabled_; |
+#if defined(OS_MACOSX) |
+ typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap; |
+ TextureToIOSurfaceMap texture_to_io_surface_map_; |
+#endif |
+ |
DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); |
}; |
@@ -1883,6 +1929,11 @@ |
texture_units_[tt].bound_texture_external_oes = info; |
glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id()); |
} |
+ if (feature_info_->feature_flags().arb_texture_rectangle) { |
+ info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB); |
+ texture_units_[tt].bound_texture_rectangle_arb = info; |
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id()); |
+ } |
info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP); |
texture_units_[tt].bound_texture_cube_map = info; |
glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id()); |
@@ -2103,6 +2154,8 @@ |
} else { |
resources.OES_standard_derivatives = |
feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0; |
+ resources.ARB_texture_rectangle = |
+ feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0; |
} |
vertex_translator_.reset(new ShaderTranslator); |
@@ -2306,6 +2359,11 @@ |
if (texture->IsStreamTexture() && stream_texture_manager_) { |
stream_texture_manager_->DestroyStreamTexture(service_id); |
} |
+#if defined(OS_MACOSX) |
+ if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) { |
+ ReleaseIOSurfaceForTexture(service_id); |
+ } |
+#endif |
glDeleteTextures(1, &service_id); |
RemoveTextureInfo(client_ids[ii]); |
} |
@@ -2618,6 +2676,14 @@ |
offscreen_saved_color_texture_.reset(); |
offscreen_resolved_frame_buffer_.reset(); |
offscreen_resolved_color_texture_.reset(); |
+ |
+#if defined(OS_MACOSX) |
+ for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin(); |
+ it != texture_to_io_surface_map_.end(); ++it) { |
+ CFRelease(it->second); |
+ } |
+ texture_to_io_surface_map_.clear(); |
+#endif |
} |
bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent, |
@@ -3131,6 +3197,9 @@ |
stream_tex->Update(); |
} |
break; |
+ case GL_TEXTURE_RECTANGLE_ARB: |
+ unit.bound_texture_rectangle_arb = info; |
+ break; |
default: |
NOTREACHED(); // Validation should prevent us getting here. |
break; |
@@ -3473,6 +3542,20 @@ |
} |
} |
return true; |
+ case GL_TEXTURE_BINDING_RECTANGLE_ARB: |
+ *num_written = 1; |
+ if (params) { |
+ TextureUnit& unit = texture_units_[active_texture_unit_]; |
+ if (unit.bound_texture_rectangle_arb) { |
+ GLuint client_id = 0; |
+ texture_manager()->GetClientId( |
+ unit.bound_texture_rectangle_arb->service_id(), &client_id); |
+ *params = client_id; |
+ } else { |
+ *params = 0; |
+ } |
+ } |
+ return true; |
default: |
*num_written = util_.GLGetNumValuesReturned(pname); |
return false; |
@@ -7486,6 +7569,112 @@ |
return error::kNoError; |
} |
+#if defined(OS_MACOSX) |
+void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) { |
+ TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find( |
+ texture_id); |
+ if (it != texture_to_io_surface_map_.end()) { |
greggman
2011/11/28 22:58:11
I don't know the use case but is there any issue w
|
+ // Found a previous IOSurface bound to this texture; release it. |
+ CFTypeRef surface = it->second; |
+ CFRelease(surface); |
+ texture_to_io_surface_map_.erase(it); |
+ } |
+} |
+#endif |
+ |
+void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( |
+ GLenum target, GLsizei width, GLsizei height, |
+ GLuint io_surface_id, GLuint plane) { |
+#if defined(OS_MACOSX) |
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { |
+ SetGLError(GL_INVALID_OPERATION, |
+ "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL."); |
+ return; |
+ } |
+ |
+ IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize(); |
+ if (!surface_support) { |
+ SetGLError(GL_INVALID_OPERATION, |
+ "glTexImageIOSurface2DCHROMIUM: only supported on 10.6."); |
+ return; |
+ } |
+ |
+ if (target != GL_TEXTURE_RECTANGLE_ARB) { |
+ // This might be supported in the future, and if we could require |
+ // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we |
+ // could delete a lot of code. For now, perform strict validation so we |
+ // know what's going on. |
+ SetGLError( |
+ GL_INVALID_OPERATION, |
+ "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target"); |
+ return; |
+ } |
+ |
+ TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); |
+ if (!info) { |
+ SetGLError(GL_INVALID_OPERATION, |
+ "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound"); |
+ return; |
+ } |
+ if (info == texture_manager()->GetDefaultTextureInfo(target)) { |
greggman
2011/11/28 22:58:11
This check is not needed. GetTextureInfoForTarget
|
+ // Maybe this is conceptually valid, but disallow it to avoid accidents. |
+ SetGLError(GL_INVALID_OPERATION, |
+ "glTexImageIOSurface2DCHROMIUM: can't bind default texture"); |
+ return; |
+ } |
+ |
+ // Look up the new IOSurface. Note that because of asynchrony |
+ // between processes this might fail; during live resizing the |
+ // plugin process might allocate and release an IOSurface before |
+ // this process gets a chance to look it up. Hold on to any old |
+ // IOSurface in this case. |
+ CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id); |
+ if (!surface) { |
+ SetGLError(GL_INVALID_OPERATION, |
+ "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID"); |
+ return; |
+ } |
+ |
+ // Release any IOSurface previously bound to this texture. |
+ ReleaseIOSurfaceForTexture(info->service_id()); |
+ |
+ // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails. |
+ texture_to_io_surface_map_.insert( |
+ std::make_pair(info->service_id(), surface)); |
+ |
+ CGLContextObj context = |
+ static_cast<CGLContextObj>(context_->GetHandle()); |
+ |
+ CGLError err = surface_support->CGLTexImageIOSurface2D( |
+ context, |
+ target, |
+ GL_RGBA, |
+ width, |
+ height, |
+ GL_BGRA, |
+ GL_UNSIGNED_INT_8_8_8_8_REV, |
+ surface, |
+ plane); |
+ |
+ if (err != kCGLNoError) { |
+ SetGLError( |
+ GL_INVALID_OPERATION, |
+ "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D"); |
+ return; |
+ } |
+ |
+ texture_manager()->SetLevelInfo( |
+ feature_info_, info, |
+ target, 0, GL_RGBA, width, height, 1, 0, |
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true); |
greggman
2011/11/28 22:58:11
Do you need to check in feature_info that GL_BGRA
|
+ |
+#else |
+ SetGLError(GL_INVALID_OPERATION, |
+ "glTexImageIOSurface2DCHROMIUM: not supported."); |
+#endif |
+} |
+ |
+ |
// Include the auto-generated part of this file. We split this because it means |
// we can easily edit the non-auto generated parts right here in this file |
// instead of having to edit some template or the code generator. |