OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <list> | 10 #include <list> |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 #include "gpu/command_buffer/service/renderbuffer_manager.h" | 49 #include "gpu/command_buffer/service/renderbuffer_manager.h" |
50 #include "gpu/command_buffer/service/shader_manager.h" | 50 #include "gpu/command_buffer/service/shader_manager.h" |
51 #include "gpu/command_buffer/service/shader_translator.h" | 51 #include "gpu/command_buffer/service/shader_translator.h" |
52 #include "gpu/command_buffer/service/shader_translator_cache.h" | 52 #include "gpu/command_buffer/service/shader_translator_cache.h" |
53 #include "gpu/command_buffer/service/stream_texture.h" | 53 #include "gpu/command_buffer/service/stream_texture.h" |
54 #include "gpu/command_buffer/service/stream_texture_manager.h" | 54 #include "gpu/command_buffer/service/stream_texture_manager.h" |
55 #include "gpu/command_buffer/service/texture_definition.h" | 55 #include "gpu/command_buffer/service/texture_definition.h" |
56 #include "gpu/command_buffer/service/texture_manager.h" | 56 #include "gpu/command_buffer/service/texture_manager.h" |
57 #include "gpu/command_buffer/service/vertex_attrib_manager.h" | 57 #include "gpu/command_buffer/service/vertex_attrib_manager.h" |
58 #include "gpu/command_buffer/service/vertex_array_manager.h" | 58 #include "gpu/command_buffer/service/vertex_array_manager.h" |
| 59 #include "ui/gl/async_pixel_transfer_delegate.h" |
59 #include "ui/gl/gl_image.h" | 60 #include "ui/gl/gl_image.h" |
60 #include "ui/gl/gl_implementation.h" | 61 #include "ui/gl/gl_implementation.h" |
61 #include "ui/gl/gl_surface.h" | 62 #include "ui/gl/gl_surface.h" |
62 #if defined(OS_MACOSX) | 63 #if defined(OS_MACOSX) |
63 #include "ui/surface/io_surface_support_mac.h" | 64 #include "ui/surface/io_surface_support_mac.h" |
64 #endif | 65 #endif |
65 | 66 |
66 #if !defined(GL_DEPTH24_STENCIL8) | 67 #if !defined(GL_DEPTH24_STENCIL8) |
67 #define GL_DEPTH24_STENCIL8 0x88F0 | 68 #define GL_DEPTH24_STENCIL8 0x88F0 |
68 #endif | 69 #endif |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 } | 187 } |
187 | 188 |
188 static inline GLenum GetTexInternalFormat(GLenum internal_format) { | 189 static inline GLenum GetTexInternalFormat(GLenum internal_format) { |
189 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { | 190 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { |
190 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT) | 191 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT) |
191 return GL_RGBA8; | 192 return GL_RGBA8; |
192 } | 193 } |
193 return internal_format; | 194 return internal_format; |
194 } | 195 } |
195 | 196 |
| 197 // TODO(epenner): Could the above function be merged into this and removed? |
| 198 static inline GLenum GetTexInternalFormat(GLenum internal_format, |
| 199 GLenum format, |
| 200 GLenum type) { |
| 201 GLenum gl_internal_format = GetTexInternalFormat(internal_format); |
| 202 |
| 203 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) |
| 204 return gl_internal_format; |
| 205 |
| 206 if (type == GL_FLOAT) { |
| 207 switch (format) { |
| 208 case GL_RGBA: |
| 209 gl_internal_format = GL_RGBA32F_ARB; |
| 210 break; |
| 211 case GL_RGB: |
| 212 gl_internal_format = GL_RGB32F_ARB; |
| 213 break; |
| 214 case GL_LUMINANCE_ALPHA: |
| 215 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB; |
| 216 break; |
| 217 case GL_LUMINANCE: |
| 218 gl_internal_format = GL_LUMINANCE32F_ARB; |
| 219 break; |
| 220 case GL_ALPHA: |
| 221 gl_internal_format = GL_ALPHA32F_ARB; |
| 222 break; |
| 223 default: |
| 224 NOTREACHED(); |
| 225 break; |
| 226 } |
| 227 } else if (type == GL_HALF_FLOAT_OES) { |
| 228 switch (format) { |
| 229 case GL_RGBA: |
| 230 gl_internal_format = GL_RGBA16F_ARB; |
| 231 break; |
| 232 case GL_RGB: |
| 233 gl_internal_format = GL_RGB16F_ARB; |
| 234 break; |
| 235 case GL_LUMINANCE_ALPHA: |
| 236 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB; |
| 237 break; |
| 238 case GL_LUMINANCE: |
| 239 gl_internal_format = GL_LUMINANCE16F_ARB; |
| 240 break; |
| 241 case GL_ALPHA: |
| 242 gl_internal_format = GL_ALPHA16F_ARB; |
| 243 break; |
| 244 default: |
| 245 NOTREACHED(); |
| 246 break; |
| 247 } |
| 248 } |
| 249 return gl_internal_format; |
| 250 } |
| 251 |
196 static void WrappedTexImage2D( | 252 static void WrappedTexImage2D( |
197 GLenum target, | 253 GLenum target, |
198 GLint level, | 254 GLint level, |
199 GLenum internal_format, | 255 GLenum internal_format, |
200 GLsizei width, | 256 GLsizei width, |
201 GLsizei height, | 257 GLsizei height, |
202 GLint border, | 258 GLint border, |
203 GLenum format, | 259 GLenum format, |
204 GLenum type, | 260 GLenum type, |
205 const void* pixels) { | 261 const void* pixels) { |
206 GLenum gl_internal_format = GetTexInternalFormat(internal_format); | |
207 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { | |
208 if (type == GL_FLOAT) { | |
209 switch (format) { | |
210 case GL_RGBA: | |
211 gl_internal_format = GL_RGBA32F_ARB; | |
212 break; | |
213 case GL_RGB: | |
214 gl_internal_format = GL_RGB32F_ARB; | |
215 break; | |
216 case GL_LUMINANCE_ALPHA: | |
217 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB; | |
218 break; | |
219 case GL_LUMINANCE: | |
220 gl_internal_format = GL_LUMINANCE32F_ARB; | |
221 break; | |
222 case GL_ALPHA: | |
223 gl_internal_format = GL_ALPHA32F_ARB; | |
224 break; | |
225 default: | |
226 NOTREACHED(); | |
227 break; | |
228 } | |
229 } else if (type == GL_HALF_FLOAT_OES) { | |
230 switch (format) { | |
231 case GL_RGBA: | |
232 gl_internal_format = GL_RGBA16F_ARB; | |
233 break; | |
234 case GL_RGB: | |
235 gl_internal_format = GL_RGB16F_ARB; | |
236 break; | |
237 case GL_LUMINANCE_ALPHA: | |
238 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB; | |
239 break; | |
240 case GL_LUMINANCE: | |
241 gl_internal_format = GL_LUMINANCE16F_ARB; | |
242 break; | |
243 case GL_ALPHA: | |
244 gl_internal_format = GL_ALPHA16F_ARB; | |
245 break; | |
246 default: | |
247 NOTREACHED(); | |
248 break; | |
249 } | |
250 } | |
251 } | |
252 glTexImage2D( | 262 glTexImage2D( |
253 target, level, gl_internal_format, width, height, border, format, type, | 263 target, level, GetTexInternalFormat(internal_format, format, type), |
254 pixels); | 264 width, height, border, format, type, pixels); |
255 } | 265 } |
256 | 266 |
257 // Wrapper for glEnable/glDisable that doesn't suck. | 267 // Wrapper for glEnable/glDisable that doesn't suck. |
258 static void EnableDisable(GLenum pname, bool enable) { | 268 static void EnableDisable(GLenum pname, bool enable) { |
259 if (enable) { | 269 if (enable) { |
260 glEnable(pname); | 270 glEnable(pname); |
261 } else { | 271 } else { |
262 glDisable(pname); | 272 glDisable(pname); |
263 } | 273 } |
264 } | 274 } |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 const char* msg); | 555 const char* msg); |
546 virtual void SetGLErrorInvalidEnum(const char* function_name, | 556 virtual void SetGLErrorInvalidEnum(const char* function_name, |
547 GLenum value, | 557 GLenum value, |
548 const char* label); | 558 const char* label); |
549 virtual void SetResizeCallback( | 559 virtual void SetResizeCallback( |
550 const base::Callback<void(gfx::Size)>& callback) OVERRIDE; | 560 const base::Callback<void(gfx::Size)>& callback) OVERRIDE; |
551 | 561 |
552 virtual void SetMsgCallback(const MsgCallback& callback) OVERRIDE; | 562 virtual void SetMsgCallback(const MsgCallback& callback) OVERRIDE; |
553 | 563 |
554 virtual void SetStreamTextureManager(StreamTextureManager* manager) OVERRIDE; | 564 virtual void SetStreamTextureManager(StreamTextureManager* manager) OVERRIDE; |
| 565 |
| 566 virtual gfx::AsyncPixelTransferDelegate* |
| 567 GetAsyncPixelTransferDelegate() OVERRIDE; |
| 568 virtual void SetAsyncPixelTransferDelegate( |
| 569 gfx::AsyncPixelTransferDelegate* delegate) OVERRIDE; |
| 570 |
555 virtual bool GetServiceTextureId(uint32 client_texture_id, | 571 virtual bool GetServiceTextureId(uint32 client_texture_id, |
556 uint32* service_texture_id) OVERRIDE; | 572 uint32* service_texture_id) OVERRIDE; |
557 | 573 |
558 virtual uint32 GetGLError() OVERRIDE; | 574 virtual uint32 GetGLError() OVERRIDE; |
559 | 575 |
560 virtual uint32 GetTextureUploadCount() OVERRIDE; | 576 virtual uint32 GetTextureUploadCount() OVERRIDE; |
561 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; | 577 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; |
562 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE; | 578 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE; |
563 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE; | 579 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE; |
564 | 580 |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 GLenum target, | 783 GLenum target, |
768 GLint level, | 784 GLint level, |
769 GLint xoffset, | 785 GLint xoffset, |
770 GLint yoffset, | 786 GLint yoffset, |
771 GLsizei width, | 787 GLsizei width, |
772 GLsizei height, | 788 GLsizei height, |
773 GLenum format, | 789 GLenum format, |
774 GLenum type, | 790 GLenum type, |
775 const void * data); | 791 const void * data); |
776 | 792 |
| 793 // Extra validation for async tex(Sub)Image2D. |
| 794 bool ValidateAsyncTransfer( |
| 795 const char* function_name, |
| 796 TextureManager::TextureInfo* info, |
| 797 GLenum target, |
| 798 GLint level, |
| 799 const void * data); |
| 800 |
777 // Wrapper for TexImageIOSurface2DCHROMIUM. | 801 // Wrapper for TexImageIOSurface2DCHROMIUM. |
778 void DoTexImageIOSurface2DCHROMIUM( | 802 void DoTexImageIOSurface2DCHROMIUM( |
779 GLenum target, | 803 GLenum target, |
780 GLsizei width, | 804 GLsizei width, |
781 GLsizei height, | 805 GLsizei height, |
782 GLuint io_surface_id, | 806 GLuint io_surface_id, |
783 GLuint plane); | 807 GLuint plane); |
784 | 808 |
785 void DoCopyTextureCHROMIUM( | 809 void DoCopyTextureCHROMIUM( |
786 GLenum target, | 810 GLenum target, |
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1591 | 1615 |
1592 scoped_ptr<QueryManager> query_manager_; | 1616 scoped_ptr<QueryManager> query_manager_; |
1593 | 1617 |
1594 scoped_ptr<VertexArrayManager> vertex_array_manager_; | 1618 scoped_ptr<VertexArrayManager> vertex_array_manager_; |
1595 | 1619 |
1596 base::Callback<void(gfx::Size)> resize_callback_; | 1620 base::Callback<void(gfx::Size)> resize_callback_; |
1597 | 1621 |
1598 MsgCallback msg_callback_; | 1622 MsgCallback msg_callback_; |
1599 | 1623 |
1600 StreamTextureManager* stream_texture_manager_; | 1624 StreamTextureManager* stream_texture_manager_; |
| 1625 scoped_ptr<gfx::AsyncPixelTransferDelegate> async_pixel_transfer_delegate_; |
1601 | 1626 |
1602 // The format of the back buffer_ | 1627 // The format of the back buffer_ |
1603 GLenum back_buffer_color_format_; | 1628 GLenum back_buffer_color_format_; |
1604 bool back_buffer_has_depth_; | 1629 bool back_buffer_has_depth_; |
1605 bool back_buffer_has_stencil_; | 1630 bool back_buffer_has_stencil_; |
1606 | 1631 |
1607 // Backbuffer attachments that are currently undefined. | 1632 // Backbuffer attachments that are currently undefined. |
1608 uint32 backbuffer_needs_clear_bits_; | 1633 uint32 backbuffer_needs_clear_bits_; |
1609 | 1634 |
1610 bool teximage2d_faster_than_texsubimage2d_; | 1635 bool teximage2d_faster_than_texsubimage2d_; |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2382 DoBindFramebuffer(GL_FRAMEBUFFER, 0); | 2407 DoBindFramebuffer(GL_FRAMEBUFFER, 0); |
2383 DoBindRenderbuffer(GL_RENDERBUFFER, 0); | 2408 DoBindRenderbuffer(GL_RENDERBUFFER, 0); |
2384 | 2409 |
2385 // AMD and Intel drivers on Mac OS apparently get gl_PointCoord | 2410 // AMD and Intel drivers on Mac OS apparently get gl_PointCoord |
2386 // backward from the spec and this setting makes them work | 2411 // backward from the spec and this setting makes them work |
2387 // correctly. rdar://problem/11883495 | 2412 // correctly. rdar://problem/11883495 |
2388 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) { | 2413 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) { |
2389 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); | 2414 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); |
2390 } | 2415 } |
2391 | 2416 |
| 2417 // Create a delegate to perform async pixel transfers. |
| 2418 async_pixel_transfer_delegate_ = |
| 2419 gfx::AsyncPixelTransferDelegate::Create(context.get()); |
| 2420 |
2392 return true; | 2421 return true; |
2393 } | 2422 } |
2394 | 2423 |
2395 void GLES2DecoderImpl::UpdateCapabilities() { | 2424 void GLES2DecoderImpl::UpdateCapabilities() { |
2396 util_.set_num_compressed_texture_formats( | 2425 util_.set_num_compressed_texture_formats( |
2397 validators_->compressed_texture_format.GetValues().size()); | 2426 validators_->compressed_texture_format.GetValues().size()); |
2398 util_.set_num_shader_binary_formats( | 2427 util_.set_num_shader_binary_formats( |
2399 validators_->shader_binary_format.GetValues().size()); | 2428 validators_->shader_binary_format.GetValues().size()); |
2400 } | 2429 } |
2401 | 2430 |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2649 | 2678 |
2650 bool GLES2DecoderImpl::MakeCurrent() { | 2679 bool GLES2DecoderImpl::MakeCurrent() { |
2651 if (!context_.get() || !context_->MakeCurrent(surface_.get())) | 2680 if (!context_.get() || !context_->MakeCurrent(surface_.get())) |
2652 return false; | 2681 return false; |
2653 | 2682 |
2654 if (WasContextLost()) { | 2683 if (WasContextLost()) { |
2655 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent."; | 2684 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent."; |
2656 return false; | 2685 return false; |
2657 } | 2686 } |
2658 | 2687 |
| 2688 // TODO(epenner): Is there a better place to do this? Transfers |
| 2689 // can complete any time we yield the main thread. So we *must* |
| 2690 // process transfers after any such yield, before resuming. |
| 2691 bool frame_buffer_dirty = false; |
| 2692 bool texture_dirty = false; |
| 2693 texture_manager()->BindFinishedAsyncPixelTransfers( |
| 2694 &texture_dirty, &frame_buffer_dirty); |
| 2695 // Texture unit zero might be stomped. |
| 2696 if (texture_dirty) |
| 2697 RestoreCurrentTexture2DBindings(); |
| 2698 // A texture attached to frame-buffer might have changed size. |
| 2699 if (frame_buffer_dirty) { |
| 2700 clear_state_dirty_ = true; |
| 2701 // TODO(gman): If textures tracked which framebuffers they were attached to |
| 2702 // we could just mark those framebuffers as not complete. |
| 2703 framebuffer_manager()->IncFramebufferStateChangeCount(); |
| 2704 } |
| 2705 |
2659 return true; | 2706 return true; |
2660 } | 2707 } |
2661 | 2708 |
2662 void GLES2DecoderImpl::ReleaseCurrent() { | 2709 void GLES2DecoderImpl::ReleaseCurrent() { |
2663 if (context_.get()) | 2710 if (context_.get()) |
2664 context_->ReleaseCurrent(surface_.get()); | 2711 context_->ReleaseCurrent(surface_.get()); |
2665 } | 2712 } |
2666 | 2713 |
2667 void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() { | 2714 void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() { |
2668 RenderbufferManager::RenderbufferInfo* renderbuffer = | 2715 RenderbufferManager::RenderbufferInfo* renderbuffer = |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2879 } | 2926 } |
2880 | 2927 |
2881 void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) { | 2928 void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) { |
2882 msg_callback_ = callback; | 2929 msg_callback_ = callback; |
2883 } | 2930 } |
2884 | 2931 |
2885 void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) { | 2932 void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) { |
2886 stream_texture_manager_ = manager; | 2933 stream_texture_manager_ = manager; |
2887 } | 2934 } |
2888 | 2935 |
| 2936 gfx::AsyncPixelTransferDelegate* |
| 2937 GLES2DecoderImpl::GetAsyncPixelTransferDelegate() { |
| 2938 return async_pixel_transfer_delegate_.get(); |
| 2939 } |
| 2940 |
| 2941 void GLES2DecoderImpl::SetAsyncPixelTransferDelegate( |
| 2942 gfx::AsyncPixelTransferDelegate* delegate) { |
| 2943 async_pixel_transfer_delegate_ = make_scoped_ptr(delegate); |
| 2944 } |
| 2945 |
2889 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id, | 2946 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id, |
2890 uint32* service_texture_id) { | 2947 uint32* service_texture_id) { |
2891 TextureManager::TextureInfo* texture = | 2948 TextureManager::TextureInfo* texture = |
2892 texture_manager()->GetTextureInfo(client_texture_id); | 2949 texture_manager()->GetTextureInfo(client_texture_id); |
2893 if (texture) { | 2950 if (texture) { |
2894 *service_texture_id = texture->service_id(); | 2951 *service_texture_id = texture->service_id(); |
2895 return true; | 2952 return true; |
2896 } | 2953 } |
2897 return false; | 2954 return false; |
2898 } | 2955 } |
(...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3621 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) { | 3678 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) { |
3622 SetGLError(GL_INVALID_OPERATION, | 3679 SetGLError(GL_INVALID_OPERATION, |
3623 "glBindTexture", "illegal target for stream texture."); | 3680 "glBindTexture", "illegal target for stream texture."); |
3624 return; | 3681 return; |
3625 } | 3682 } |
3626 LogClientServiceForInfo(info, client_id, "glBindTexture"); | 3683 LogClientServiceForInfo(info, client_id, "glBindTexture"); |
3627 if (info->target() == 0) { | 3684 if (info->target() == 0) { |
3628 texture_manager()->SetInfoTarget(info, target); | 3685 texture_manager()->SetInfoTarget(info, target); |
3629 } | 3686 } |
3630 glBindTexture(target, info->service_id()); | 3687 glBindTexture(target, info->service_id()); |
| 3688 |
3631 TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; | 3689 TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; |
3632 unit.bind_target = target; | 3690 unit.bind_target = target; |
3633 switch (target) { | 3691 switch (target) { |
3634 case GL_TEXTURE_2D: | 3692 case GL_TEXTURE_2D: |
3635 unit.bound_texture_2d = info; | 3693 unit.bound_texture_2d = info; |
3636 break; | 3694 break; |
3637 case GL_TEXTURE_CUBE_MAP: | 3695 case GL_TEXTURE_CUBE_MAP: |
3638 unit.bound_texture_cube_map = info; | 3696 unit.bound_texture_cube_map = info; |
3639 break; | 3697 break; |
3640 case GL_TEXTURE_EXTERNAL_OES: | 3698 case GL_TEXTURE_EXTERNAL_OES: |
(...skipping 4267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7908 } | 7966 } |
7909 GLenum type = 0; | 7967 GLenum type = 0; |
7910 GLenum format = 0; | 7968 GLenum format = 0; |
7911 if (!info->GetLevelType(target, level, &type, &format) || | 7969 if (!info->GetLevelType(target, level, &type, &format) || |
7912 !info->ValidForTexture( | 7970 !info->ValidForTexture( |
7913 target, level, xoffset, yoffset, width, height, format, type)) { | 7971 target, level, xoffset, yoffset, width, height, format, type)) { |
7914 SetGLError(GL_INVALID_VALUE, | 7972 SetGLError(GL_INVALID_VALUE, |
7915 "glCopyTexSubImage2D", "bad dimensions."); | 7973 "glCopyTexSubImage2D", "bad dimensions."); |
7916 return; | 7974 return; |
7917 } | 7975 } |
| 7976 if (info->AsyncTransferIsInProgress()) { |
| 7977 SetGLError(GL_INVALID_OPERATION, |
| 7978 "glCopyTexSubImage2D", "async upload pending for texture"); |
| 7979 return; |
| 7980 } |
7918 | 7981 |
7919 // Check we have compatible formats. | 7982 // Check we have compatible formats. |
7920 GLenum read_format = GetBoundReadFrameBufferInternalFormat(); | 7983 GLenum read_format = GetBoundReadFrameBufferInternalFormat(); |
7921 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format); | 7984 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format); |
7922 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format); | 7985 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format); |
7923 | 7986 |
7924 if (!channels_needed || | 7987 if (!channels_needed || |
7925 (channels_needed & channels_exist) != channels_needed) { | 7988 (channels_needed & channels_exist) != channels_needed) { |
7926 SetGLError( | 7989 SetGLError( |
7927 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format"); | 7990 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format"); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8033 if (format != internal_format) { | 8096 if (format != internal_format) { |
8034 SetGLError(GL_INVALID_OPERATION, | 8097 SetGLError(GL_INVALID_OPERATION, |
8035 function_name, "format does not match internal format."); | 8098 function_name, "format does not match internal format."); |
8036 return false; | 8099 return false; |
8037 } | 8100 } |
8038 if (type != current_type) { | 8101 if (type != current_type) { |
8039 SetGLError(GL_INVALID_OPERATION, | 8102 SetGLError(GL_INVALID_OPERATION, |
8040 function_name, "type does not match type of texture."); | 8103 function_name, "type does not match type of texture."); |
8041 return false; | 8104 return false; |
8042 } | 8105 } |
| 8106 if (info->AsyncTransferIsInProgress()) { |
| 8107 SetGLError(GL_INVALID_OPERATION, |
| 8108 function_name, "async upload pending for texture"); |
| 8109 return false; |
| 8110 } |
8043 if (!info->ValidForTexture( | 8111 if (!info->ValidForTexture( |
8044 target, level, xoffset, yoffset, width, height, format, type)) { | 8112 target, level, xoffset, yoffset, width, height, format, type)) { |
8045 SetGLError(GL_INVALID_VALUE, function_name, "bad dimensions."); | 8113 SetGLError(GL_INVALID_VALUE, function_name, "bad dimensions."); |
8046 return false; | 8114 return false; |
8047 } | 8115 } |
8048 if ((GLES2Util::GetChannelsForFormat(format) & | 8116 if ((GLES2Util::GetChannelsForFormat(format) & |
8049 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) { | 8117 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) { |
8050 SetGLError( | 8118 SetGLError( |
8051 GL_INVALID_OPERATION, | 8119 GL_INVALID_OPERATION, |
8052 function_name, "can not supply data for depth or stencil textures"); | 8120 function_name, "can not supply data for depth or stencil textures"); |
(...skipping 1621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9674 SetGLError(GL_INVALID_OPERATION, | 9742 SetGLError(GL_INVALID_OPERATION, |
9675 "glTraceEndCHROMIUM", "no trace begin found"); | 9743 "glTraceEndCHROMIUM", "no trace begin found"); |
9676 return; | 9744 return; |
9677 } | 9745 } |
9678 | 9746 |
9679 linked_ptr<GPUTrace> trace = gpu_trace_stack_.top(); | 9747 linked_ptr<GPUTrace> trace = gpu_trace_stack_.top(); |
9680 trace->EnableEndTrace(); | 9748 trace->EnableEndTrace(); |
9681 gpu_trace_stack_.pop(); | 9749 gpu_trace_stack_.pop(); |
9682 } | 9750 } |
9683 | 9751 |
| 9752 bool GLES2DecoderImpl::ValidateAsyncTransfer( |
| 9753 const char* function_name, |
| 9754 TextureManager::TextureInfo* info, |
| 9755 GLenum target, |
| 9756 GLint level, |
| 9757 const void * data) { |
| 9758 // We only support async uploads to 2D textures for now. |
| 9759 if (GL_TEXTURE_2D != target) { |
| 9760 SetGLErrorInvalidEnum(function_name, target, "target"); |
| 9761 return false; |
| 9762 } |
| 9763 // We only support uploads to level zero for now. |
| 9764 if (level != 0) { |
| 9765 SetGLError(GL_INVALID_VALUE, function_name, "level != 0"); |
| 9766 return false; |
| 9767 } |
| 9768 // A transfer buffer must be bound, even for asyncTexImage2D. |
| 9769 if (data == NULL) { |
| 9770 SetGLError(GL_INVALID_OPERATION, function_name, "buffer == 0"); |
| 9771 return false; |
| 9772 } |
| 9773 // We only support one async transfer in progress. |
| 9774 if (!info || info->AsyncTransferIsInProgress()) { |
| 9775 SetGLError(GL_INVALID_OPERATION, |
| 9776 function_name, "transfer already in progress"); |
| 9777 return false; |
| 9778 } |
| 9779 return true; |
| 9780 } |
| 9781 |
9684 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( | 9782 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( |
9685 uint32 immediate_data_size, const gles2::AsyncTexImage2DCHROMIUM& c) { | 9783 uint32 immediate_data_size, const gles2::AsyncTexImage2DCHROMIUM& c) { |
9686 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM"); | 9784 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM"); |
9687 | |
9688 // TODO: This is a copy of HandleTexImage2D validation. Merge | |
9689 // as much of it as possible. | |
9690 tex_image_2d_failed_ = true; | |
9691 GLenum target = static_cast<GLenum>(c.target); | 9785 GLenum target = static_cast<GLenum>(c.target); |
9692 GLint level = static_cast<GLint>(c.level); | 9786 GLint level = static_cast<GLint>(c.level); |
9693 GLint internal_format = static_cast<GLint>(c.internalformat); | 9787 GLint internal_format = static_cast<GLint>(c.internalformat); |
9694 GLsizei width = static_cast<GLsizei>(c.width); | 9788 GLsizei width = static_cast<GLsizei>(c.width); |
9695 GLsizei height = static_cast<GLsizei>(c.height); | 9789 GLsizei height = static_cast<GLsizei>(c.height); |
9696 GLint border = static_cast<GLint>(c.border); | 9790 GLint border = static_cast<GLint>(c.border); |
9697 GLenum format = static_cast<GLenum>(c.format); | 9791 GLenum format = static_cast<GLenum>(c.format); |
9698 GLenum type = static_cast<GLenum>(c.type); | 9792 GLenum type = static_cast<GLenum>(c.type); |
9699 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id); | 9793 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id); |
9700 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset); | 9794 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset); |
9701 uint32 pixels_size; | 9795 uint32 pixels_size; |
| 9796 |
| 9797 // TODO(epenner): Move this and copies of this memory validation |
| 9798 // into ValidateTexImage2D step. |
9702 if (!GLES2Util::ComputeImageDataSizes( | 9799 if (!GLES2Util::ComputeImageDataSizes( |
9703 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL, | 9800 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL, |
9704 NULL)) { | 9801 NULL)) { |
9705 return error::kOutOfBounds; | 9802 return error::kOutOfBounds; |
9706 } | 9803 } |
9707 const void* pixels = NULL; | 9804 const void* pixels = NULL; |
9708 if (pixels_shm_id != 0 || pixels_shm_offset != 0) { | 9805 if (pixels_shm_id != 0 || pixels_shm_offset != 0) { |
9709 pixels = GetSharedMemoryAs<const void*>( | 9806 pixels = GetSharedMemoryAs<const void*>( |
9710 pixels_shm_id, pixels_shm_offset, pixels_size); | 9807 pixels_shm_id, pixels_shm_offset, pixels_size); |
9711 if (!pixels) { | 9808 if (!pixels) { |
9712 return error::kOutOfBounds; | 9809 return error::kOutOfBounds; |
9713 } | 9810 } |
9714 } | 9811 } |
9715 | 9812 |
9716 // TODO(epenner): Do this via an async task. | 9813 // All the normal glTexSubImage2D validation. |
9717 DoTexImage2D( | 9814 if (!ValidateTexImage2D( |
9718 target, level, internal_format, width, height, border, format, type, | 9815 "glAsyncTexImage2DCHROMIUM", target, level, internal_format, |
9719 pixels, pixels_size); | 9816 width, height, border, format, type, pixels, pixels_size)) { |
| 9817 return error::kNoError; |
| 9818 } |
| 9819 |
| 9820 // Extra async validation. |
| 9821 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); |
| 9822 if (!ValidateAsyncTransfer( |
| 9823 "glAsyncTexImage2DCHROMIUM", info, target, level, pixels)) |
| 9824 return error::kNoError; |
| 9825 |
| 9826 // Don't allow async redefinition of a textures. |
| 9827 if (info->IsDefined()) { |
| 9828 SetGLError(GL_INVALID_OPERATION, |
| 9829 "glAsyncTexImage2DCHROMIUM", "already defined"); |
| 9830 return error::kNoError; |
| 9831 } |
| 9832 |
| 9833 // We know the memory/size is safe, so get the real shared memory since |
| 9834 // it might need to be duped to prevent use-after-free of the memory. |
| 9835 Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id); |
| 9836 base::SharedMemory* shared_memory = buffer.shared_memory; |
| 9837 uint32 shm_size = buffer.size; |
| 9838 uint32 shm_data_offset = c.pixels_shm_offset; |
| 9839 uint32 shm_data_size = pixels_size; |
| 9840 |
| 9841 // Set up the async state if needed, and make the texture |
| 9842 // immutable so the async state stays valid. The level info |
| 9843 // is set up lazily when the transfer completes. |
| 9844 DCHECK(!info->GetAsyncTransferState()); |
| 9845 info->SetAsyncTransferState( |
| 9846 async_pixel_transfer_delegate_-> |
| 9847 CreatePixelTransferState(info->service_id())); |
| 9848 info->SetImmutable(true); |
| 9849 |
| 9850 // Issue the async call and set up the texture. |
| 9851 GLenum gl_internal_format = |
| 9852 GetTexInternalFormat(internal_format, format, type); |
| 9853 gfx::AsyncTexImage2DParams tex_params = {target, level, gl_internal_format, |
| 9854 width, height, border, format, type}; |
| 9855 gfx::AsyncMemoryParams mem_params = {shared_memory, shm_size, |
| 9856 shm_data_offset, shm_data_size}; |
| 9857 |
| 9858 // Add a pending transfer to the texture manager, which will bind the |
| 9859 // transfer data to the texture and set the level info at the same time, |
| 9860 // after the the transfer is complete. |
| 9861 texture_manager()->AddPendingAsyncPixelTransfer( |
| 9862 info->GetAsyncTransferState()->AsWeakPtr(), info); |
| 9863 |
| 9864 async_pixel_transfer_delegate_->AsyncTexImage2D( |
| 9865 info->GetAsyncTransferState(), tex_params, mem_params); |
9720 return error::kNoError; | 9866 return error::kNoError; |
9721 } | 9867 } |
9722 | 9868 |
9723 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM( | 9869 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM( |
9724 uint32 immediate_data_size, const gles2::AsyncTexSubImage2DCHROMIUM& c) { | 9870 uint32 immediate_data_size, const gles2::AsyncTexSubImage2DCHROMIUM& c) { |
9725 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM"); | 9871 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM"); |
9726 | |
9727 // TODO: This is a copy of HandleTexSubImage2D validation. Merge | |
9728 // as much of it as possible. | |
9729 GLenum target = static_cast<GLenum>(c.target); | 9872 GLenum target = static_cast<GLenum>(c.target); |
9730 GLint level = static_cast<GLint>(c.level); | 9873 GLint level = static_cast<GLint>(c.level); |
9731 GLint xoffset = static_cast<GLint>(c.xoffset); | 9874 GLint xoffset = static_cast<GLint>(c.xoffset); |
9732 GLint yoffset = static_cast<GLint>(c.yoffset); | 9875 GLint yoffset = static_cast<GLint>(c.yoffset); |
9733 GLsizei width = static_cast<GLsizei>(c.width); | 9876 GLsizei width = static_cast<GLsizei>(c.width); |
9734 GLsizei height = static_cast<GLsizei>(c.height); | 9877 GLsizei height = static_cast<GLsizei>(c.height); |
9735 GLenum format = static_cast<GLenum>(c.format); | 9878 GLenum format = static_cast<GLenum>(c.format); |
9736 GLenum type = static_cast<GLenum>(c.type); | 9879 GLenum type = static_cast<GLenum>(c.type); |
| 9880 |
| 9881 // TODO(epenner): Move this and copies of this memory validation |
| 9882 // into ValidateTexSubImage2D step. |
9737 uint32 data_size; | 9883 uint32 data_size; |
9738 if (!GLES2Util::ComputeImageDataSizes( | 9884 if (!GLES2Util::ComputeImageDataSizes( |
9739 width, height, format, type, state_.unpack_alignment, &data_size, | 9885 width, height, format, type, state_.unpack_alignment, &data_size, |
9740 NULL, NULL)) { | 9886 NULL, NULL)) { |
9741 return error::kOutOfBounds; | 9887 return error::kOutOfBounds; |
9742 } | 9888 } |
9743 const void* pixels = GetSharedMemoryAs<const void*>( | 9889 const void* pixels = GetSharedMemoryAs<const void*>( |
9744 c.data_shm_id, c.data_shm_offset, data_size); | 9890 c.data_shm_id, c.data_shm_offset, data_size); |
9745 if (pixels == NULL) { | 9891 |
9746 return error::kOutOfBounds; | 9892 // All the normal glTexSubImage2D validation. |
| 9893 error::Error error = error::kNoError; |
| 9894 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM", |
| 9895 target, level, xoffset, yoffset, width, height, format, type, pixels)) { |
| 9896 return error; |
9747 } | 9897 } |
9748 | 9898 |
9749 // TODO(epenner): Do this via an async task. | 9899 // Extra async validation. |
9750 return DoTexSubImage2D( | 9900 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); |
9751 target, level, xoffset, yoffset, width, height, format, type, pixels); | 9901 if (!ValidateAsyncTransfer( |
| 9902 "glAsyncTexSubImage2DCHROMIUM", info, target, level, pixels)) |
| 9903 return error::kNoError; |
| 9904 |
| 9905 // Guarantee async textures are always 'cleared' as follows: |
| 9906 // - AsyncTexImage2D can not redefine an existing texture |
| 9907 // - AsyncTexImage2D must initialize the entire image via non-null buffer. |
| 9908 // - AsyncTexSubImage2D clears synchronously if not already cleared. |
| 9909 // - Textures become immutable after an async call. |
| 9910 // This way we know in all cases that an async texture is always clear. |
| 9911 if (!info->SafeToRenderFrom()) { |
| 9912 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) { |
| 9913 SetGLError(GL_OUT_OF_MEMORY, |
| 9914 "glAsyncTexSubImage2DCHROMIUM","dimensions too big"); |
| 9915 return error::kNoError; |
| 9916 } |
| 9917 } |
| 9918 |
| 9919 // We know the memory/size is safe, so get the real shared memory since |
| 9920 // it might need to be duped to prevent use-after-free of the memory. |
| 9921 Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id); |
| 9922 base::SharedMemory* shared_memory = buffer.shared_memory; |
| 9923 uint32 shm_size = buffer.size; |
| 9924 uint32 shm_data_offset = c.data_shm_offset; |
| 9925 uint32 shm_data_size = data_size; |
| 9926 |
| 9927 if (!info->GetAsyncTransferState()) { |
| 9928 // Set up the async state if needed, and make the texture |
| 9929 // immutable so the async state stays valid. |
| 9930 info->SetAsyncTransferState( |
| 9931 async_pixel_transfer_delegate_-> |
| 9932 CreatePixelTransferState(info->service_id())); |
| 9933 info->SetImmutable(true); |
| 9934 } |
| 9935 |
| 9936 gfx::AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset, |
| 9937 width, height, format, type}; |
| 9938 gfx::AsyncMemoryParams mem_params = {shared_memory, shm_size, |
| 9939 shm_data_offset, shm_data_size}; |
| 9940 async_pixel_transfer_delegate_->AsyncTexSubImage2D( |
| 9941 info->GetAsyncTransferState(), tex_params, mem_params); |
| 9942 return error::kNoError; |
9752 } | 9943 } |
9753 | 9944 |
9754 // Include the auto-generated part of this file. We split this because it means | 9945 // Include the auto-generated part of this file. We split this because it means |
9755 // we can easily edit the non-auto generated parts right here in this file | 9946 // we can easily edit the non-auto generated parts right here in this file |
9756 // instead of having to edit some template or the code generator. | 9947 // instead of having to edit some template or the code generator. |
9757 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 9948 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
9758 | 9949 |
9759 } // namespace gles2 | 9950 } // namespace gles2 |
9760 } // namespace gpu | 9951 } // namespace gpu |
OLD | NEW |