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
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
16 #include "base/at_exit.h"
17 #include "base/bind.h"
18 #include "base/callback_helpers.h"
19 #include "base/command_line.h"
20 #include "base/debug/trace_event.h"
21 #include "base/debug/trace_event_synthetic_delay.h"
22 #include "base/float_util.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/numerics/safe_math.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_split.h"
27 #include "build/build_config.h"
28 #define GLES2_GPU_SERVICE 1
29 #include "gpu/command_buffer/common/debug_marker_manager.h"
30 #include "gpu/command_buffer/common/gles2_cmd_format.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/mailbox.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
36 #include "gpu/command_buffer/service/buffer_manager.h"
37 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
38 #include "gpu/command_buffer/service/context_group.h"
39 #include "gpu/command_buffer/service/context_state.h"
40 #include "gpu/command_buffer/service/error_state.h"
41 #include "gpu/command_buffer/service/feature_info.h"
42 #include "gpu/command_buffer/service/framebuffer_manager.h"
43 #include "gpu/command_buffer/service/gl_utils.h"
44 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
45 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
46 #include "gpu/command_buffer/service/gpu_state_tracer.h"
47 #include "gpu/command_buffer/service/gpu_switches.h"
48 #include "gpu/command_buffer/service/gpu_tracer.h"
49 #include "gpu/command_buffer/service/image_manager.h"
50 #include "gpu/command_buffer/service/mailbox_manager.h"
51 #include "gpu/command_buffer/service/memory_tracking.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/shader_translator_cache.h"
58 #include "gpu/command_buffer/service/texture_manager.h"
59 #include "gpu/command_buffer/service/valuebuffer_manager.h"
60 #include "gpu/command_buffer/service/vertex_array_manager.h"
61 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
62 #include "third_party/smhasher/src/City.h"
63 #include "ui/gl/gl_fence.h"
64 #include "ui/gl/gl_image.h"
65 #include "ui/gl/gl_implementation.h"
66 #include "ui/gl/gl_surface.h"
68 #if defined(OS_MACOSX)
69 #include <IOSurface/IOSurfaceAPI.h>
70 // Note that this must be included after gl_bindings.h to avoid conflicts.
71 #include <OpenGL/CGLIOSurface.h>
75 #include "base/win/win_util.h"
83 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
84 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
85 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
86 static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
88 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
91 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
94 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
95 GLenum precision_type,
96 GLint *range, GLint *precision) {
97 switch (precision_type) {
101 // These values are for a 32-bit twos-complement integer format.
107 case GL_MEDIUM_FLOAT:
109 // These values are for an IEEE single-precision floating-point format.
119 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
120 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
121 // This function is sometimes defined even though it's really just
122 // a stub, so we need to set range and precision as if it weren't
123 // defined before calling it.
124 // On Mac OS with some GPUs, calling this generates a
125 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
127 glGetShaderPrecisionFormat(shader_type, precision_type,
130 // TODO(brianderson): Make the following official workarounds.
132 // Some drivers have bugs where they report the ranges as a negative number.
133 // Taking the absolute value here shouldn't hurt because negative numbers
134 // aren't expected anyway.
135 range[0] = abs(range[0]);
136 range[1] = abs(range[1]);
138 // If the driver reports a precision for highp float that isn't actually
139 // highp, don't pretend like it's supported because shader compilation will
141 if (precision_type == GL_HIGH_FLOAT &&
142 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
150 static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
151 switch (plane_transform) {
152 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
153 return gfx::OVERLAY_TRANSFORM_NONE;
154 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
155 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
156 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
157 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
158 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
159 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
160 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
161 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
162 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
163 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
165 return gfx::OVERLAY_TRANSFORM_INVALID;
171 class GLES2DecoderImpl;
173 // Local versions of the SET_GL_ERROR macros
174 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
175 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
176 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
177 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
178 function_name, value, label)
179 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
180 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
181 function_name, pname)
182 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
183 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
185 #define LOCAL_PEEK_GL_ERROR(function_name) \
186 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
187 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
188 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
189 #define LOCAL_PERFORMANCE_WARNING(msg) \
190 PerformanceWarning(__FILE__, __LINE__, msg)
191 #define LOCAL_RENDER_WARNING(msg) \
192 RenderWarning(__FILE__, __LINE__, msg)
194 // Check that certain assumptions the code makes are true. There are places in
195 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
196 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
197 // a few others) are 32bits. If they are not 32bits the code will have to change
198 // to call those GL functions with service side memory and then copy the results
199 // to shared memory, converting the sizes.
200 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
201 GLint_not_same_size_as_uint32);
202 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
203 GLint_not_same_size_as_uint32);
204 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
205 GLfloat_not_same_size_as_float);
207 // TODO(kbr): the use of this anonymous namespace core dumps the
208 // linker on Mac OS X 10.6 when the symbol ordering file is used
211 // Returns the address of the first byte after a struct.
212 template <typename T>
213 const void* AddressAfterStruct(const T& pod) {
214 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
217 // Returns the address of the frst byte after the struct or NULL if size >
218 // immediate_data_size.
219 template <typename RETURN_TYPE, typename COMMAND_TYPE>
220 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
222 uint32 immediate_data_size) {
223 return (size <= immediate_data_size) ?
224 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
228 // Computes the data size for certain gl commands like glUniform.
229 bool ComputeDataSize(
232 unsigned int elements_per_unit,
235 if (!SafeMultiplyUint32(count, size, &value)) {
238 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
245 // Return true if a character belongs to the ASCII subset as defined in
246 // GLSL ES 1.0 spec section 3.1.
247 static bool CharacterIsValidForGLES(unsigned char c) {
248 // Printing characters are valid except " $ ` @ \ ' DEL.
249 if (c >= 32 && c <= 126 &&
258 // Horizontal tab, line feed, vertical tab, form feed, carriage return
260 if (c >= 9 && c <= 13) {
267 static bool StringIsValidForGLES(const char* str) {
268 for (; *str; ++str) {
269 if (!CharacterIsValidForGLES(*str)) {
276 // This class prevents any GL errors that occur when it is in scope from
277 // being reported to the client.
278 class ScopedGLErrorSuppressor {
280 explicit ScopedGLErrorSuppressor(
281 const char* function_name, ErrorState* error_state);
282 ~ScopedGLErrorSuppressor();
284 const char* function_name_;
285 ErrorState* error_state_;
286 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
289 // Temporarily changes a decoder's bound texture and restore it when this
290 // object goes out of scope. Also temporarily switches to using active texture
291 // unit zero in case the client has changed that to something invalid.
292 class ScopedTextureBinder {
294 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
295 ~ScopedTextureBinder();
298 ContextState* state_;
300 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
303 // Temporarily changes a decoder's bound render buffer and restore it when this
304 // object goes out of scope.
305 class ScopedRenderBufferBinder {
307 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
308 ~ScopedRenderBufferBinder();
311 ContextState* state_;
312 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
315 // Temporarily changes a decoder's bound frame buffer and restore it when this
316 // object goes out of scope.
317 class ScopedFrameBufferBinder {
319 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
320 ~ScopedFrameBufferBinder();
323 GLES2DecoderImpl* decoder_;
324 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
327 // Temporarily changes a decoder's bound frame buffer to a resolved version of
328 // the multisampled offscreen render buffer if that buffer is multisampled, and,
329 // if it is bound or enforce_internal_framebuffer is true. If internal is
330 // true, the resolved framebuffer is not visible to the parent.
331 class ScopedResolvedFrameBufferBinder {
333 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
334 bool enforce_internal_framebuffer,
336 ~ScopedResolvedFrameBufferBinder();
339 GLES2DecoderImpl* decoder_;
340 bool resolve_and_bind_;
341 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
344 class ScopedModifyPixels {
346 explicit ScopedModifyPixels(TextureRef* ref);
347 ~ScopedModifyPixels();
353 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
355 ref_->texture()->OnWillModifyPixels();
358 ScopedModifyPixels::~ScopedModifyPixels() {
360 ref_->texture()->OnDidModifyPixels();
363 class ScopedRenderTo {
365 explicit ScopedRenderTo(Framebuffer* framebuffer);
369 const Framebuffer* framebuffer_;
372 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
373 : framebuffer_(framebuffer) {
375 framebuffer_->OnWillRenderTo();
378 ScopedRenderTo::~ScopedRenderTo() {
380 framebuffer_->OnDidRenderTo();
383 // Encapsulates an OpenGL texture.
386 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
389 // Create a new render texture.
392 // Set the initial size and format of a render texture or resize it.
393 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
395 // Copy the contents of the currently bound frame buffer.
396 void Copy(const gfx::Size& size, GLenum format);
398 // Destroy the render texture. This must be explicitly called before
399 // destroying this object.
402 // Invalidate the texture. This can be used when a context is lost and it is
403 // not possible to make it current in order to free the resource.
410 gfx::Size size() const {
415 MemoryTypeTracker memory_tracker_;
416 ContextState* state_;
417 size_t bytes_allocated_;
420 DISALLOW_COPY_AND_ASSIGN(BackTexture);
423 // Encapsulates an OpenGL render buffer of any format.
424 class BackRenderbuffer {
426 explicit BackRenderbuffer(
427 RenderbufferManager* renderbuffer_manager,
428 MemoryTracker* memory_tracker,
429 ContextState* state);
432 // Create a new render buffer.
435 // Set the initial size and format of a render buffer or resize it.
436 bool AllocateStorage(const FeatureInfo* feature_info,
437 const gfx::Size& size,
441 // Destroy the render buffer. This must be explicitly called before destroying
445 // Invalidate the render buffer. This can be used when a context is lost and
446 // it is not possible to make it current in order to free the resource.
454 RenderbufferManager* renderbuffer_manager_;
455 MemoryTypeTracker memory_tracker_;
456 ContextState* state_;
457 size_t bytes_allocated_;
459 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
462 // Encapsulates an OpenGL frame buffer.
463 class BackFramebuffer {
465 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
468 // Create a new frame buffer.
471 // Attach a color render buffer to a frame buffer.
472 void AttachRenderTexture(BackTexture* texture);
474 // Attach a render buffer to a frame buffer. Note that this unbinds any
475 // currently bound frame buffer.
476 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
478 // Destroy the frame buffer. This must be explicitly called before destroying
482 // Invalidate the frame buffer. This can be used when a context is lost and it
483 // is not possible to make it current in order to free the resource.
486 // See glCheckFramebufferStatusEXT.
487 GLenum CheckStatus();
494 GLES2DecoderImpl* decoder_;
496 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
499 struct FenceCallback {
500 explicit FenceCallback()
501 : fence(gfx::GLFence::Create()) {
504 std::vector<base::Closure> callbacks;
505 scoped_ptr<gfx::GLFence> fence;
508 class AsyncUploadTokenCompletionObserver
509 : public AsyncPixelTransferCompletionObserver {
511 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
512 : async_upload_token_(async_upload_token) {
515 void DidComplete(const AsyncMemoryParams& mem_params) override {
516 DCHECK(mem_params.buffer().get());
517 void* data = mem_params.GetDataAddress();
518 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
519 sync->SetAsyncUploadToken(async_upload_token_);
523 ~AsyncUploadTokenCompletionObserver() override {}
525 uint32 async_upload_token_;
527 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
530 // } // anonymous namespace.
533 const unsigned int GLES2Decoder::kDefaultStencilMask =
534 static_cast<unsigned int>(-1);
536 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
537 uint32* service_texture_id) {
541 GLES2Decoder::GLES2Decoder()
542 : initialized_(false),
544 log_commands_(false) {
547 GLES2Decoder::~GLES2Decoder() {
550 void GLES2Decoder::BeginDecoding() {}
552 void GLES2Decoder::EndDecoding() {}
554 // This class implements GLES2Decoder so we don't have to expose all the GLES2
555 // cmd stuff to outside this class.
556 class GLES2DecoderImpl : public GLES2Decoder,
557 public FramebufferManager::TextureDetachObserver,
558 public ErrorStateClient {
560 explicit GLES2DecoderImpl(ContextGroup* group);
561 ~GLES2DecoderImpl() override;
563 // Overridden from AsyncAPIInterface.
564 Error DoCommand(unsigned int command,
565 unsigned int arg_count,
566 const void* args) override;
568 error::Error DoCommands(unsigned int num_commands,
571 int* entries_processed) override;
573 template <bool DebugImpl>
574 error::Error DoCommandsImpl(unsigned int num_commands,
577 int* entries_processed);
579 // Overridden from AsyncAPIInterface.
580 const char* GetCommandName(unsigned int command_id) const override;
582 // Overridden from GLES2Decoder.
583 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
584 const scoped_refptr<gfx::GLContext>& context,
586 const gfx::Size& size,
587 const DisallowedFeatures& disallowed_features,
588 const std::vector<int32>& attribs) override;
589 void Destroy(bool have_context) override;
590 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
591 void ProduceFrontBuffer(const Mailbox& mailbox) override;
592 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
593 void UpdateParentTextureInfo();
594 bool MakeCurrent() override;
595 GLES2Util* GetGLES2Util() override { return &util_; }
596 gfx::GLContext* GetGLContext() override { return context_.get(); }
597 ContextGroup* GetContextGroup() override { return group_.get(); }
598 Capabilities GetCapabilities() override;
599 void RestoreState(const ContextState* prev_state) override;
601 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
602 void RestoreAllTextureUnitBindings(
603 const ContextState* prev_state) const override {
604 state_.RestoreAllTextureUnitBindings(prev_state);
606 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
607 state_.RestoreActiveTextureUnitBinding(target);
609 void RestoreBufferBindings() const override {
610 state_.RestoreBufferBindings();
612 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
613 void RestoreProgramBindings() const override {
614 state_.RestoreProgramBindings();
616 void RestoreTextureUnitBindings(unsigned unit) const override {
617 state_.RestoreTextureUnitBindings(unit, NULL);
619 void RestoreFramebufferBindings() const override;
620 void RestoreRenderbufferBindings() override;
621 void RestoreTextureState(unsigned service_id) const override;
623 void ClearAllAttributes() const override;
624 void RestoreAllAttributes() const override;
626 QueryManager* GetQueryManager() override { return query_manager_.get(); }
627 VertexArrayManager* GetVertexArrayManager() override {
628 return vertex_array_manager_.get();
630 ImageManager* GetImageManager() override { return image_manager_.get(); }
631 bool ProcessPendingQueries(bool did_finish) override;
632 bool HasMoreIdleWork() override;
633 void PerformIdleWork() override;
635 void WaitForReadPixels(base::Closure callback) override;
637 void SetResizeCallback(
638 const base::Callback<void(gfx::Size, float)>& callback) override;
640 Logger* GetLogger() override;
642 void BeginDecoding() override;
643 void EndDecoding() override;
645 ErrorState* GetErrorState() override;
646 const ContextState* GetContextState() override { return &state_; }
648 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
649 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
651 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
652 void ResetAsyncPixelTransferManagerForTest() override;
653 void SetAsyncPixelTransferManagerForTest(
654 AsyncPixelTransferManager* manager) override;
655 void SetIgnoreCachedStateForTest(bool ignore) override;
656 void ProcessFinishedAsyncTransfers();
658 bool GetServiceTextureId(uint32 client_texture_id,
659 uint32* service_texture_id) override;
661 uint32 GetTextureUploadCount() override;
662 base::TimeDelta GetTotalTextureUploadTime() override;
663 base::TimeDelta GetTotalProcessingCommandsTime() override;
664 void AddProcessingCommandsTime(base::TimeDelta) override;
666 // Restores the current state to the user's settings.
667 void RestoreCurrentFramebufferBindings();
669 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
670 void ApplyDirtyState();
672 // These check the state of the currently bound framebuffer or the
673 // backbuffer if no framebuffer is bound.
674 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
675 // check with all attached and enabled color attachments.
676 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
677 bool BoundFramebufferHasDepthAttachment();
678 bool BoundFramebufferHasStencilAttachment();
680 error::ContextLostReason GetContextLostReason() override;
682 // Overridden from FramebufferManager::TextureDetachObserver:
683 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
685 // Overriden from ErrorStateClient.
686 void OnContextLostError() override;
687 void OnOutOfMemoryError() override;
689 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
690 void EnsureRenderbufferBound();
692 // Helpers to facilitate calling into compatible extensions.
693 static void RenderbufferStorageMultisampleHelper(
694 const FeatureInfo* feature_info,
697 GLenum internal_format,
701 void BlitFramebufferHelper(GLint srcX0,
713 friend class ScopedFrameBufferBinder;
714 friend class ScopedResolvedFrameBufferBinder;
715 friend class BackFramebuffer;
717 // Initialize or re-initialize the shader translator.
718 bool InitializeShaderTranslator();
720 void UpdateCapabilities();
722 // Helpers for the glGen and glDelete functions.
723 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
724 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
725 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
726 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
727 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
728 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
729 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
730 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
731 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
732 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
733 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
734 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
735 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
736 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
738 // Helper for async upload token completion notification callback.
739 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
740 uint32 sync_data_shm_id,
741 uint32 sync_data_shm_offset);
746 void OnFboChanged() const;
747 void OnUseFramebuffer() const;
749 // TODO(gman): Cache these pointers?
750 BufferManager* buffer_manager() {
751 return group_->buffer_manager();
754 RenderbufferManager* renderbuffer_manager() {
755 return group_->renderbuffer_manager();
758 FramebufferManager* framebuffer_manager() {
759 return group_->framebuffer_manager();
762 ValuebufferManager* valuebuffer_manager() {
763 return group_->valuebuffer_manager();
766 ProgramManager* program_manager() {
767 return group_->program_manager();
770 ShaderManager* shader_manager() {
771 return group_->shader_manager();
774 ShaderTranslatorCache* shader_translator_cache() {
775 return group_->shader_translator_cache();
778 const TextureManager* texture_manager() const {
779 return group_->texture_manager();
782 TextureManager* texture_manager() {
783 return group_->texture_manager();
786 MailboxManager* mailbox_manager() {
787 return group_->mailbox_manager();
790 ImageManager* image_manager() { return image_manager_.get(); }
792 VertexArrayManager* vertex_array_manager() {
793 return vertex_array_manager_.get();
796 MemoryTracker* memory_tracker() {
797 return group_->memory_tracker();
800 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
801 MemoryTracker* tracker = memory_tracker();
803 return tracker->EnsureGPUMemoryAvailable(estimated_size);
808 bool IsOffscreenBufferMultisampled() const {
809 return offscreen_target_samples_ > 1;
812 // Creates a Texture for the given texture.
813 TextureRef* CreateTexture(
814 GLuint client_id, GLuint service_id) {
815 return texture_manager()->CreateTexture(client_id, service_id);
818 // Gets the texture info for the given texture. Returns NULL if none exists.
819 TextureRef* GetTexture(GLuint client_id) const {
820 return texture_manager()->GetTexture(client_id);
823 // Deletes the texture info for the given texture.
824 void RemoveTexture(GLuint client_id) {
825 texture_manager()->RemoveTexture(client_id);
828 // Get the size (in pixels) of the currently bound frame buffer (either FBO
829 // or regular back buffer).
830 gfx::Size GetBoundReadFrameBufferSize();
832 // Get the format of the currently bound frame buffer (either FBO or regular
834 GLenum GetBoundReadFrameBufferTextureType();
835 GLenum GetBoundReadFrameBufferInternalFormat();
836 GLenum GetBoundDrawFrameBufferInternalFormat();
838 // Wrapper for CompressedTexImage2D commands.
839 error::Error DoCompressedTexImage2D(
842 GLenum internal_format,
849 // Wrapper for CompressedTexSubImage2D.
850 void DoCompressedTexSubImage2D(
861 // Wrapper for CopyTexImage2D.
862 void DoCopyTexImage2D(
865 GLenum internal_format,
872 // Wrapper for SwapBuffers.
873 void DoSwapBuffers();
875 // Wrapper for CopyTexSubImage2D.
876 void DoCopyTexSubImage2D(
886 // Validation for TexSubImage2D.
887 bool ValidateTexSubImage2D(
889 const char* function_name,
900 // Wrapper for TexSubImage2D.
901 error::Error DoTexSubImage2D(
912 // Extra validation for async tex(Sub)Image2D.
913 bool ValidateAsyncTransfer(
914 const char* function_name,
915 TextureRef* texture_ref,
920 // Wrapper for TexImageIOSurface2DCHROMIUM.
921 void DoTexImageIOSurface2DCHROMIUM(
925 GLuint io_surface_id,
928 void DoCopyTextureCHROMIUM(
933 GLenum internal_format,
936 // Wrapper for TexStorage2DEXT.
937 void DoTexStorage2DEXT(
940 GLenum internal_format,
944 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
945 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
947 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
948 GLenum target, const GLbyte* data);
950 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
951 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
954 bool DoIsValuebufferCHROMIUM(GLuint client_id);
955 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
956 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
957 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
958 void DoUniformValueBufferCHROMIUM(GLint location,
960 GLenum subscription);
962 void DoBindTexImage2DCHROMIUM(
965 void DoReleaseTexImage2DCHROMIUM(
969 void DoTraceEndCHROMIUM(void);
971 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
973 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
975 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
976 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
978 // Creates a Program for the given program.
979 Program* CreateProgram(
980 GLuint client_id, GLuint service_id) {
981 return program_manager()->CreateProgram(client_id, service_id);
984 // Gets the program info for the given program. Returns NULL if none exists.
985 Program* GetProgram(GLuint client_id) {
986 return program_manager()->GetProgram(client_id);
990 void LogClientServiceMapping(
991 const char* /* function_name */,
992 GLuint /* client_id */,
993 GLuint /* service_id */) {
996 void LogClientServiceForInfo(
997 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1000 void LogClientServiceMapping(
1001 const char* function_name, GLuint client_id, GLuint service_id) {
1002 if (service_logging_) {
1003 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1004 << ": client_id = " << client_id
1005 << ", service_id = " << service_id;
1008 template<typename T>
1009 void LogClientServiceForInfo(
1010 T* info, GLuint client_id, const char* function_name) {
1012 LogClientServiceMapping(function_name, client_id, info->service_id());
1017 // Gets the program info for the given program. If it's not a program
1018 // generates a GL error. Returns NULL if not program.
1019 Program* GetProgramInfoNotShader(
1020 GLuint client_id, const char* function_name) {
1021 Program* program = GetProgram(client_id);
1023 if (GetShader(client_id)) {
1025 GL_INVALID_OPERATION, function_name, "shader passed for program");
1027 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1030 LogClientServiceForInfo(program, client_id, function_name);
1035 // Creates a Shader for the given shader.
1036 Shader* CreateShader(
1039 GLenum shader_type) {
1040 return shader_manager()->CreateShader(
1041 client_id, service_id, shader_type);
1044 // Gets the shader info for the given shader. Returns NULL if none exists.
1045 Shader* GetShader(GLuint client_id) {
1046 return shader_manager()->GetShader(client_id);
1049 // Gets the shader info for the given shader. If it's not a shader generates a
1050 // GL error. Returns NULL if not shader.
1051 Shader* GetShaderInfoNotProgram(
1052 GLuint client_id, const char* function_name) {
1053 Shader* shader = GetShader(client_id);
1055 if (GetProgram(client_id)) {
1057 GL_INVALID_OPERATION, function_name, "program passed for shader");
1060 GL_INVALID_VALUE, function_name, "unknown shader");
1063 LogClientServiceForInfo(shader, client_id, function_name);
1067 // Creates a buffer info for the given buffer.
1068 void CreateBuffer(GLuint client_id, GLuint service_id) {
1069 return buffer_manager()->CreateBuffer(client_id, service_id);
1072 // Gets the buffer info for the given buffer.
1073 Buffer* GetBuffer(GLuint client_id) {
1074 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1078 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1079 // on glDeleteBuffers so we can make sure the user does not try to render
1080 // with deleted buffers.
1081 void RemoveBuffer(GLuint client_id);
1083 // Creates a framebuffer info for the given framebuffer.
1084 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1085 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1088 // Gets the framebuffer info for the given framebuffer.
1089 Framebuffer* GetFramebuffer(GLuint client_id) {
1090 return framebuffer_manager()->GetFramebuffer(client_id);
1093 // Removes the framebuffer info for the given framebuffer.
1094 void RemoveFramebuffer(GLuint client_id) {
1095 framebuffer_manager()->RemoveFramebuffer(client_id);
1098 // Creates a renderbuffer info for the given renderbuffer.
1099 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1100 return renderbuffer_manager()->CreateRenderbuffer(
1101 client_id, service_id);
1104 // Gets the renderbuffer info for the given renderbuffer.
1105 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1106 return renderbuffer_manager()->GetRenderbuffer(client_id);
1109 // Removes the renderbuffer info for the given renderbuffer.
1110 void RemoveRenderbuffer(GLuint client_id) {
1111 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1114 // Creates a valuebuffer info for the given valuebuffer.
1115 void CreateValuebuffer(GLuint client_id) {
1116 return valuebuffer_manager()->CreateValuebuffer(client_id);
1119 // Gets the valuebuffer info for a given valuebuffer.
1120 Valuebuffer* GetValuebuffer(GLuint client_id) {
1121 return valuebuffer_manager()->GetValuebuffer(client_id);
1124 // Removes the valuebuffer info for the given valuebuffer.
1125 void RemoveValuebuffer(GLuint client_id) {
1126 valuebuffer_manager()->RemoveValuebuffer(client_id);
1129 // Gets the vertex attrib manager for the given vertex array.
1130 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1131 VertexAttribManager* info =
1132 vertex_array_manager()->GetVertexAttribManager(client_id);
1136 // Removes the vertex attrib manager for the given vertex array.
1137 void RemoveVertexAttribManager(GLuint client_id) {
1138 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1141 // Creates a vertex attrib manager for the given vertex array.
1142 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1145 bool client_visible) {
1146 return vertex_array_manager()->CreateVertexAttribManager(
1147 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1150 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1151 void DoBindUniformLocationCHROMIUM(
1152 GLuint client_id, GLint location, const char* name);
1154 error::Error GetAttribLocationHelper(
1155 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1156 const std::string& name_str);
1158 error::Error GetUniformLocationHelper(
1159 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1160 const std::string& name_str);
1162 // Helper for glShaderSource.
1163 error::Error ShaderSourceHelper(
1164 GLuint client_id, const char* data, uint32 data_size);
1166 // Clear any textures used by the current program.
1167 bool ClearUnclearedTextures();
1169 // Clears any uncleared attachments attached to the given frame buffer.
1170 // Returns false if there was a generated GL error.
1171 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1173 // overridden from GLES2Decoder
1174 bool ClearLevel(unsigned service_id,
1175 unsigned bind_target,
1178 unsigned internal_format,
1183 bool is_texture_immutable) override;
1185 // Restore all GL state that affects clearing.
1186 void RestoreClearState();
1188 // Remembers the state of some capabilities.
1189 // Returns: true if glEnable/glDisable should actually be called.
1190 bool SetCapabilityState(GLenum cap, bool enabled);
1192 // Check that the currently bound framebuffers are valid.
1193 // Generates GL error if not.
1194 bool CheckBoundFramebuffersValid(const char* func_name);
1196 // Check that the currently bound read framebuffer has a color image
1197 // attached. Generates GL error if not.
1198 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1200 // Check that the currently bound read framebuffer's color image
1201 // isn't the target texture of the glCopyTex{Sub}Image2D.
1202 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1204 // Check if a framebuffer meets our requirements.
1205 bool CheckFramebufferValid(
1206 Framebuffer* framebuffer,
1208 const char* func_name);
1210 // Check if the current valuebuffer exists and is valid. If not generates
1211 // the appropriate GL error. Returns true if the current valuebuffer is in
1213 bool CheckCurrentValuebuffer(const char* function_name);
1215 // Check if the current valuebuffer exists and is valiud and that the
1216 // value buffer is actually subscribed to the given subscription
1217 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1218 const char* function_name);
1220 // Check if the location can be used for the given subscription target. If not
1221 // generates the appropriate GL error. Returns true if the location is usable
1222 bool CheckSubscriptionTarget(GLint location,
1223 GLenum subscription,
1224 const char* function_name);
1226 // Checks if the current program exists and is valid. If not generates the
1227 // appropriate GL error. Returns true if the current program is in a usable
1229 bool CheckCurrentProgram(const char* function_name);
1231 // Checks if the current program exists and is valid and that location is not
1232 // -1. If the current program is not valid generates the appropriate GL
1233 // error. Returns true if the current program is in a usable state and
1234 // location is not -1.
1235 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1237 // Checks if the current program samples a texture that is also the color
1238 // image of the current bound framebuffer, i.e., the source and destination
1239 // of the draw operation are the same.
1240 bool CheckDrawingFeedbackLoops();
1242 // Checks if |api_type| is valid for the given uniform
1243 // If the api type is not valid generates the appropriate GL
1244 // error. Returns true if |api_type| is valid for the uniform
1245 bool CheckUniformForApiType(const Program::UniformInfo* info,
1246 const char* function_name,
1247 Program::UniformApiType api_type);
1249 // Gets the type of a uniform for a location in the current program. Sets GL
1250 // errors if the current program is not valid. Returns true if the current
1251 // program is valid and the location exists. Adjusts count so it
1252 // does not overflow the uniform.
1253 bool PrepForSetUniformByLocation(GLint fake_location,
1254 const char* function_name,
1255 Program::UniformApiType api_type,
1256 GLint* real_location,
1260 // Gets the service id for any simulated backbuffer fbo.
1261 GLuint GetBackbufferServiceId() const;
1263 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1264 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1266 // Helper for glGetVertexAttrib
1267 void GetVertexAttribHelper(
1268 const VertexAttrib* attrib, GLenum pname, GLint* param);
1270 // Wrapper for glCreateProgram
1271 bool CreateProgramHelper(GLuint client_id);
1273 // Wrapper for glCreateShader
1274 bool CreateShaderHelper(GLenum type, GLuint client_id);
1276 // Wrapper for glActiveTexture
1277 void DoActiveTexture(GLenum texture_unit);
1279 // Wrapper for glAttachShader
1280 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1282 // Wrapper for glBindBuffer since we need to track the current targets.
1283 void DoBindBuffer(GLenum target, GLuint buffer);
1285 // Wrapper for glBindFramebuffer since we need to track the current targets.
1286 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1288 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1289 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1291 // Wrapper for glBindTexture since we need to track the current targets.
1292 void DoBindTexture(GLenum target, GLuint texture);
1294 // Wrapper for glBindVertexArrayOES
1295 void DoBindVertexArrayOES(GLuint array);
1296 void EmulateVertexArrayState();
1298 // Wrapper for glBlitFramebufferCHROMIUM.
1299 void DoBlitFramebufferCHROMIUM(
1300 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1301 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1302 GLbitfield mask, GLenum filter);
1304 // Wrapper for glBufferSubData.
1305 void DoBufferSubData(
1306 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1308 // Wrapper for glCheckFramebufferStatus
1309 GLenum DoCheckFramebufferStatus(GLenum target);
1311 // Wrapper for glClear
1312 error::Error DoClear(GLbitfield mask);
1314 // Wrappers for various state.
1315 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1316 void DoSampleCoverage(GLclampf value, GLboolean invert);
1318 // Wrapper for glCompileShader.
1319 void DoCompileShader(GLuint shader);
1321 // Wrapper for glDetachShader
1322 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1324 // Wrapper for glDisable
1325 void DoDisable(GLenum cap);
1327 // Wrapper for glDisableVertexAttribArray.
1328 void DoDisableVertexAttribArray(GLuint index);
1330 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1332 void DoDiscardFramebufferEXT(GLenum target,
1333 GLsizei numAttachments,
1334 const GLenum* attachments);
1336 // Wrapper for glEnable
1337 void DoEnable(GLenum cap);
1339 // Wrapper for glEnableVertexAttribArray.
1340 void DoEnableVertexAttribArray(GLuint index);
1342 // Wrapper for glFinish.
1345 // Wrapper for glFlush.
1348 // Wrapper for glFramebufferRenderbufffer.
1349 void DoFramebufferRenderbuffer(
1350 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1351 GLuint renderbuffer);
1353 // Wrapper for glFramebufferTexture2D.
1354 void DoFramebufferTexture2D(
1355 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1358 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1359 void DoFramebufferTexture2DMultisample(
1360 GLenum target, GLenum attachment, GLenum textarget,
1361 GLuint texture, GLint level, GLsizei samples);
1363 // Common implementation for both DoFramebufferTexture2D wrappers.
1364 void DoFramebufferTexture2DCommon(const char* name,
1365 GLenum target, GLenum attachment, GLenum textarget,
1366 GLuint texture, GLint level, GLsizei samples);
1368 // Wrapper for glGenerateMipmap
1369 void DoGenerateMipmap(GLenum target);
1371 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1372 // to account for different pname values defined in different extension
1374 GLenum AdjustGetPname(GLenum pname);
1376 // Wrapper for DoGetBooleanv.
1377 void DoGetBooleanv(GLenum pname, GLboolean* params);
1379 // Wrapper for DoGetFloatv.
1380 void DoGetFloatv(GLenum pname, GLfloat* params);
1382 // Wrapper for glGetFramebufferAttachmentParameteriv.
1383 void DoGetFramebufferAttachmentParameteriv(
1384 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1386 // Wrapper for glGetIntegerv.
1387 void DoGetIntegerv(GLenum pname, GLint* params);
1389 // Gets the max value in a range in a buffer.
1390 GLuint DoGetMaxValueInBufferCHROMIUM(
1391 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1393 // Wrapper for glGetBufferParameteriv.
1394 void DoGetBufferParameteriv(
1395 GLenum target, GLenum pname, GLint* params);
1397 // Wrapper for glGetProgramiv.
1398 void DoGetProgramiv(
1399 GLuint program_id, GLenum pname, GLint* params);
1401 // Wrapper for glRenderbufferParameteriv.
1402 void DoGetRenderbufferParameteriv(
1403 GLenum target, GLenum pname, GLint* params);
1405 // Wrapper for glGetShaderiv
1406 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1408 // Wrappers for glGetTexParameter.
1409 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1410 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1411 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1413 // Wrappers for glGetVertexAttrib.
1414 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1415 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1417 // Wrappers for glIsXXX functions.
1418 bool DoIsEnabled(GLenum cap);
1419 bool DoIsBuffer(GLuint client_id);
1420 bool DoIsFramebuffer(GLuint client_id);
1421 bool DoIsProgram(GLuint client_id);
1422 bool DoIsRenderbuffer(GLuint client_id);
1423 bool DoIsShader(GLuint client_id);
1424 bool DoIsTexture(GLuint client_id);
1425 bool DoIsVertexArrayOES(GLuint client_id);
1427 // Wrapper for glLinkProgram
1428 void DoLinkProgram(GLuint program);
1430 // Wrapper for glRenderbufferStorage.
1431 void DoRenderbufferStorage(
1432 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1434 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1435 void DoRenderbufferStorageMultisampleCHROMIUM(
1436 GLenum target, GLsizei samples, GLenum internalformat,
1437 GLsizei width, GLsizei height);
1439 // Handler for glRenderbufferStorageMultisampleEXT
1440 // (multisampled_render_to_texture).
1441 void DoRenderbufferStorageMultisampleEXT(
1442 GLenum target, GLsizei samples, GLenum internalformat,
1443 GLsizei width, GLsizei height);
1445 // Common validation for multisample extensions.
1446 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1447 GLenum internalformat,
1451 // Verifies that the currently bound multisample renderbuffer is valid
1452 // Very slow! Only done on platforms with driver bugs that return invalid
1453 // buffers under memory pressure
1454 bool VerifyMultisampleRenderbufferIntegrity(
1455 GLuint renderbuffer, GLenum format);
1457 // Wrapper for glReleaseShaderCompiler.
1458 void DoReleaseShaderCompiler() { }
1460 // Wrappers for glTexParameter functions.
1461 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1462 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1463 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1464 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1466 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1467 // spec only these 2 functions can be used to set sampler uniforms.
1468 void DoUniform1i(GLint fake_location, GLint v0);
1469 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1470 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1471 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1472 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1474 // Wrappers for glUniformfv because some drivers don't correctly accept
1476 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1477 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1478 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1479 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1481 void DoUniformMatrix2fv(
1482 GLint fake_location, GLsizei count, GLboolean transpose,
1483 const GLfloat* value);
1484 void DoUniformMatrix3fv(
1485 GLint fake_location, GLsizei count, GLboolean transpose,
1486 const GLfloat* value);
1487 void DoUniformMatrix4fv(
1488 GLint fake_location, GLsizei count, GLboolean transpose,
1489 const GLfloat* value);
1491 bool SetVertexAttribValue(
1492 const char* function_name, GLuint index, const GLfloat* value);
1494 // Wrappers for glVertexAttrib??
1495 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1496 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1497 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1498 void DoVertexAttrib4f(
1499 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1500 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1501 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1502 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1503 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1505 // Wrapper for glViewport
1506 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1508 // Wrapper for glUseProgram
1509 void DoUseProgram(GLuint program);
1511 // Wrapper for glValidateProgram.
1512 void DoValidateProgram(GLuint program_client_id);
1514 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1515 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1516 void DoPopGroupMarkerEXT(void);
1518 // Gets the number of values that will be returned by glGetXXX. Returns
1519 // false if pname is unknown.
1520 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1522 // Checks if the current program and vertex attributes are valid for drawing.
1524 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1527 // Returns true if successful, simulated will be true if attrib0 was
1529 bool SimulateAttrib0(
1530 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1531 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1533 // If an image is bound to texture, this will call Will/DidUseTexImage
1535 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1536 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1538 // Returns false if textures were replaced.
1539 bool PrepareTexturesForRender();
1540 void RestoreStateForTextures();
1542 // Returns true if GL_FIXED attribs were simulated.
1543 bool SimulateFixedAttribs(
1544 const char* function_name,
1545 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1546 void RestoreStateForSimulatedFixedAttribs();
1548 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1549 // cases (primcount is always 1 for non-instanced).
1550 error::Error DoDrawArrays(
1551 const char* function_name,
1552 bool instanced, GLenum mode, GLint first, GLsizei count,
1554 error::Error DoDrawElements(
1555 const char* function_name,
1556 bool instanced, GLenum mode, GLsizei count, GLenum type,
1557 int32 offset, GLsizei primcount);
1559 GLenum GetBindTargetForSamplerType(GLenum type) {
1560 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1561 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1564 return GL_TEXTURE_2D;
1565 case GL_SAMPLER_CUBE:
1566 return GL_TEXTURE_CUBE_MAP;
1567 case GL_SAMPLER_EXTERNAL_OES:
1568 return GL_TEXTURE_EXTERNAL_OES;
1569 case GL_SAMPLER_2D_RECT_ARB:
1570 return GL_TEXTURE_RECTANGLE_ARB;
1577 // Gets the framebuffer info for a particular target.
1578 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1579 Framebuffer* framebuffer = NULL;
1581 case GL_FRAMEBUFFER:
1582 case GL_DRAW_FRAMEBUFFER_EXT:
1583 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1585 case GL_READ_FRAMEBUFFER_EXT:
1586 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1595 Renderbuffer* GetRenderbufferInfoForTarget(
1597 Renderbuffer* renderbuffer = NULL;
1599 case GL_RENDERBUFFER:
1600 renderbuffer = state_.bound_renderbuffer.get();
1606 return renderbuffer;
1609 // Validates the program and location for a glGetUniform call and returns
1610 // a SizeResult setup to receive the result. Returns true if glGetUniform
1611 // should be called.
1612 bool GetUniformSetup(
1613 GLuint program, GLint fake_location,
1614 uint32 shm_id, uint32 shm_offset,
1615 error::Error* error, GLint* real_location, GLuint* service_id,
1616 void** result, GLenum* result_type);
1618 void MaybeExitOnContextLost();
1619 bool WasContextLost() override;
1620 bool WasContextLostByRobustnessExtension() override;
1621 void LoseContext(uint32 reset_status) override;
1623 #if defined(OS_MACOSX)
1624 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1627 bool ValidateCompressedTexDimensions(
1628 const char* function_name,
1629 GLint level, GLsizei width, GLsizei height, GLenum format);
1630 bool ValidateCompressedTexFuncData(
1631 const char* function_name,
1632 GLsizei width, GLsizei height, GLenum format, size_t size);
1633 bool ValidateCompressedTexSubDimensions(
1634 const char* function_name,
1635 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1636 GLsizei width, GLsizei height, GLenum format,
1639 void RenderWarning(const char* filename, int line, const std::string& msg);
1640 void PerformanceWarning(
1641 const char* filename, int line, const std::string& msg);
1643 const FeatureInfo::FeatureFlags& features() const {
1644 return feature_info_->feature_flags();
1647 const FeatureInfo::Workarounds& workarounds() const {
1648 return feature_info_->workarounds();
1651 bool ShouldDeferDraws() {
1652 return !offscreen_target_frame_buffer_.get() &&
1653 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1654 surface_->DeferDraws();
1657 bool ShouldDeferReads() {
1658 return !offscreen_target_frame_buffer_.get() &&
1659 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1660 surface_->DeferDraws();
1663 error::Error WillAccessBoundFramebufferForDraw() {
1664 if (ShouldDeferDraws())
1665 return error::kDeferCommandUntilLater;
1666 if (!offscreen_target_frame_buffer_.get() &&
1667 !framebuffer_state_.bound_draw_framebuffer.get() &&
1668 !surface_->SetBackbufferAllocation(true))
1669 return error::kLostContext;
1670 return error::kNoError;
1673 error::Error WillAccessBoundFramebufferForRead() {
1674 if (ShouldDeferReads())
1675 return error::kDeferCommandUntilLater;
1676 if (!offscreen_target_frame_buffer_.get() &&
1677 !framebuffer_state_.bound_read_framebuffer.get() &&
1678 !surface_->SetBackbufferAllocation(true))
1679 return error::kLostContext;
1680 return error::kNoError;
1683 // Set remaining commands to process to 0 to force DoCommands to return
1684 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1685 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1687 void ProcessPendingReadPixels();
1688 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1690 // Generate a member function prototype for each command in an automated and
1692 #define GLES2_CMD_OP(name) \
1693 Error Handle##name(uint32 immediate_data_size, const void* data);
1695 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1699 // The GL context this decoder renders to on behalf of the client.
1700 scoped_refptr<gfx::GLSurface> surface_;
1701 scoped_refptr<gfx::GLContext> context_;
1703 // The ContextGroup for this decoder uses to track resources.
1704 scoped_refptr<ContextGroup> group_;
1706 DebugMarkerManager debug_marker_manager_;
1709 // All the state for this context.
1710 ContextState state_;
1712 // Current width and height of the offscreen frame buffer.
1713 gfx::Size offscreen_size_;
1715 // Util to help with GL.
1718 // unpack flip y as last set by glPixelStorei
1719 bool unpack_flip_y_;
1721 // unpack (un)premultiply alpha as last set by glPixelStorei
1722 bool unpack_premultiply_alpha_;
1723 bool unpack_unpremultiply_alpha_;
1725 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1726 GLuint attrib_0_buffer_id_;
1728 // The value currently in attrib_0.
1729 Vec4 attrib_0_value_;
1731 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1732 bool attrib_0_buffer_matches_value_;
1734 // The size of attrib 0.
1735 GLsizei attrib_0_size_;
1737 // The buffer used to simulate GL_FIXED attribs.
1738 GLuint fixed_attrib_buffer_id_;
1740 // The size of fiixed attrib buffer.
1741 GLsizei fixed_attrib_buffer_size_;
1743 // The offscreen frame buffer that the client renders to. With EGL, the
1744 // depth and stencil buffers are separate. With regular GL there is a single
1745 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1746 // offscreen_target_stencil_render_buffer_ is unused.
1747 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1748 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1749 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1750 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1751 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1752 GLenum offscreen_target_color_format_;
1753 GLenum offscreen_target_depth_format_;
1754 GLenum offscreen_target_stencil_format_;
1755 GLsizei offscreen_target_samples_;
1756 GLboolean offscreen_target_buffer_preserved_;
1758 // The copy that is saved when SwapBuffers is called.
1759 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1760 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1761 scoped_refptr<TextureRef>
1762 offscreen_saved_color_texture_info_;
1764 // The copy that is used as the destination for multi-sample resolves.
1765 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1766 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1767 GLenum offscreen_saved_color_format_;
1769 scoped_ptr<QueryManager> query_manager_;
1771 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1773 scoped_ptr<ImageManager> image_manager_;
1775 base::Callback<void(gfx::Size, float)> resize_callback_;
1777 WaitSyncPointCallback wait_sync_point_callback_;
1779 ShaderCacheCallback shader_cache_callback_;
1781 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1783 // The format of the back buffer_
1784 GLenum back_buffer_color_format_;
1785 bool back_buffer_has_depth_;
1786 bool back_buffer_has_stencil_;
1790 // Backbuffer attachments that are currently undefined.
1791 uint32 backbuffer_needs_clear_bits_;
1793 // The current decoder error communicates the decoder error through command
1794 // processing functions that do not return the error value. Should be set only
1795 // if not returning an error.
1796 error::Error current_decoder_error_;
1798 bool use_shader_translator_;
1799 scoped_refptr<ShaderTranslator> vertex_translator_;
1800 scoped_refptr<ShaderTranslator> fragment_translator_;
1802 DisallowedFeatures disallowed_features_;
1804 // Cached from ContextGroup
1805 const Validators* validators_;
1806 scoped_refptr<FeatureInfo> feature_info_;
1810 // Number of commands remaining to be processed in DoCommands().
1811 int commands_to_process_;
1813 bool has_robustness_extension_;
1814 GLenum reset_status_;
1815 bool reset_by_robustness_extension_;
1816 bool supports_post_sub_buffer_;
1818 // These flags are used to override the state of the shared feature_info_
1819 // member. Because the same FeatureInfo instance may be shared among many
1820 // contexts, the assumptions on the availablity of extensions in WebGL
1821 // contexts may be broken. These flags override the shared state to preserve
1823 bool force_webgl_glsl_validation_;
1824 bool derivatives_explicitly_enabled_;
1825 bool frag_depth_explicitly_enabled_;
1826 bool draw_buffers_explicitly_enabled_;
1827 bool shader_texture_lod_explicitly_enabled_;
1829 bool compile_shader_always_succeeds_;
1831 // An optional behaviour to lose the context and group when OOM.
1832 bool lose_context_when_out_of_memory_;
1835 bool service_logging_;
1837 #if defined(OS_MACOSX)
1838 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1839 TextureToIOSurfaceMap texture_to_io_surface_map_;
1842 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1844 // Cached values of the currently assigned viewport dimensions.
1845 GLsizei viewport_max_width_;
1846 GLsizei viewport_max_height_;
1848 // Command buffer stats.
1849 base::TimeDelta total_processing_commands_time_;
1851 // States related to each manager.
1852 DecoderTextureState texture_state_;
1853 DecoderFramebufferState framebuffer_state_;
1855 scoped_ptr<GPUTracer> gpu_tracer_;
1856 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1857 const unsigned char* cb_command_trace_category_;
1858 int gpu_trace_level_;
1859 bool gpu_trace_commands_;
1860 bool gpu_debug_commands_;
1862 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1864 // Used to validate multisample renderbuffers if needed
1865 GLuint validation_texture_;
1866 GLuint validation_fbo_multisample_;
1867 GLuint validation_fbo_;
1869 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
1870 uint32 immediate_data_size,
1873 // A struct to hold info about each command.
1874 struct CommandInfo {
1875 CmdHandler cmd_handler;
1876 uint8 arg_flags; // How to handle the arguments for this command
1877 uint8 cmd_flags; // How to handle this command
1878 uint16 arg_count; // How many arguments are expected for this command.
1881 // A table of CommandInfo for all the commands.
1882 static const CommandInfo command_info[kNumCommands - kStartPoint];
1884 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1887 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
1888 #define GLES2_CMD_OP(name) \
1890 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1891 cmds::name::cmd_flags, \
1892 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1895 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1899 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1900 const char* function_name, ErrorState* error_state)
1901 : function_name_(function_name),
1902 error_state_(error_state) {
1903 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1906 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1907 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1910 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1911 TextureUnit& info = state->texture_units[0];
1913 scoped_refptr<TextureRef> texture_ref;
1916 texture_ref = info.bound_texture_2d;
1918 case GL_TEXTURE_CUBE_MAP:
1919 texture_ref = info.bound_texture_cube_map;
1921 case GL_TEXTURE_EXTERNAL_OES:
1922 texture_ref = info.bound_texture_external_oes;
1924 case GL_TEXTURE_RECTANGLE_ARB:
1925 texture_ref = info.bound_texture_rectangle_arb;
1931 if (texture_ref.get()) {
1932 last_id = texture_ref->service_id();
1937 glBindTexture(target, last_id);
1938 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1941 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1946 ScopedGLErrorSuppressor suppressor(
1947 "ScopedTextureBinder::ctor", state_->GetErrorState());
1949 // TODO(apatrick): Check if there are any other states that need to be reset
1950 // before binding a new texture.
1951 glActiveTexture(GL_TEXTURE0);
1952 glBindTexture(target, id);
1955 ScopedTextureBinder::~ScopedTextureBinder() {
1956 ScopedGLErrorSuppressor suppressor(
1957 "ScopedTextureBinder::dtor", state_->GetErrorState());
1958 RestoreCurrentTextureBindings(state_, target_);
1961 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1964 ScopedGLErrorSuppressor suppressor(
1965 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1966 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1969 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1970 ScopedGLErrorSuppressor suppressor(
1971 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1972 state_->RestoreRenderbufferBindings();
1975 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1977 : decoder_(decoder) {
1978 ScopedGLErrorSuppressor suppressor(
1979 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1980 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1981 decoder->OnFboChanged();
1984 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1985 ScopedGLErrorSuppressor suppressor(
1986 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1987 decoder_->RestoreCurrentFramebufferBindings();
1990 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1991 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1992 : decoder_(decoder) {
1993 resolve_and_bind_ = (
1994 decoder_->offscreen_target_frame_buffer_.get() &&
1995 decoder_->IsOffscreenBufferMultisampled() &&
1996 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1997 enforce_internal_framebuffer));
1998 if (!resolve_and_bind_)
2001 ScopedGLErrorSuppressor suppressor(
2002 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2003 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2004 decoder_->offscreen_target_frame_buffer_->id());
2007 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2008 decoder_->offscreen_resolved_frame_buffer_.reset(
2009 new BackFramebuffer(decoder_));
2010 decoder_->offscreen_resolved_frame_buffer_->Create();
2011 decoder_->offscreen_resolved_color_texture_.reset(
2012 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2013 decoder_->offscreen_resolved_color_texture_->Create();
2015 DCHECK(decoder_->offscreen_saved_color_format_);
2016 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2017 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2019 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2020 decoder_->offscreen_resolved_color_texture_.get());
2021 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2022 GL_FRAMEBUFFER_COMPLETE) {
2023 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2024 << "because offscreen resolved FBO was incomplete.";
2028 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2030 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2032 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2033 const int width = decoder_->offscreen_size_.width();
2034 const int height = decoder_->offscreen_size_.height();
2035 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2036 decoder->BlitFramebufferHelper(0,
2044 GL_COLOR_BUFFER_BIT,
2046 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2049 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2050 if (!resolve_and_bind_)
2053 ScopedGLErrorSuppressor suppressor(
2054 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2055 decoder_->RestoreCurrentFramebufferBindings();
2056 if (decoder_->state_.enable_flags.scissor_test) {
2057 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2061 BackTexture::BackTexture(
2062 MemoryTracker* memory_tracker,
2063 ContextState* state)
2064 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2066 bytes_allocated_(0),
2070 BackTexture::~BackTexture() {
2071 // This does not destroy the render texture because that would require that
2072 // the associated GL context was current. Just check that it was explicitly
2077 void BackTexture::Create() {
2078 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2079 state_->GetErrorState());
2081 glGenTextures(1, &id_);
2082 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2083 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2084 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2085 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2086 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2088 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2089 // never called on an offscreen context, no data will ever be uploaded to the
2090 // saved offscreen color texture (it is deferred until to when SwapBuffers
2091 // is called). My idea is that some nvidia drivers might have a bug where
2092 // deleting a texture that has never been populated might cause a
2095 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2097 bytes_allocated_ = 16u * 16u * 4u;
2098 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2101 bool BackTexture::AllocateStorage(
2102 const gfx::Size& size, GLenum format, bool zero) {
2104 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2105 state_->GetErrorState());
2106 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2107 uint32 image_size = 0;
2108 GLES2Util::ComputeImageDataSizes(
2109 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
2112 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2116 scoped_ptr<char[]> zero_data;
2118 zero_data.reset(new char[image_size]);
2119 memset(zero_data.get(), 0, image_size);
2122 glTexImage2D(GL_TEXTURE_2D,
2134 bool success = glGetError() == GL_NO_ERROR;
2136 memory_tracker_.TrackMemFree(bytes_allocated_);
2137 bytes_allocated_ = image_size;
2138 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2143 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2145 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2146 state_->GetErrorState());
2147 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2148 glCopyTexImage2D(GL_TEXTURE_2D,
2157 void BackTexture::Destroy() {
2159 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2160 state_->GetErrorState());
2161 glDeleteTextures(1, &id_);
2164 memory_tracker_.TrackMemFree(bytes_allocated_);
2165 bytes_allocated_ = 0;
2168 void BackTexture::Invalidate() {
2172 BackRenderbuffer::BackRenderbuffer(
2173 RenderbufferManager* renderbuffer_manager,
2174 MemoryTracker* memory_tracker,
2175 ContextState* state)
2176 : renderbuffer_manager_(renderbuffer_manager),
2177 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2179 bytes_allocated_(0),
2183 BackRenderbuffer::~BackRenderbuffer() {
2184 // This does not destroy the render buffer because that would require that
2185 // the associated GL context was current. Just check that it was explicitly
2190 void BackRenderbuffer::Create() {
2191 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2192 state_->GetErrorState());
2194 glGenRenderbuffersEXT(1, &id_);
2197 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2198 const gfx::Size& size,
2201 ScopedGLErrorSuppressor suppressor(
2202 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2203 ScopedRenderBufferBinder binder(state_, id_);
2205 uint32 estimated_size = 0;
2206 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2207 size.width(), size.height(), samples, format, &estimated_size)) {
2211 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2216 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2221 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2228 bool success = glGetError() == GL_NO_ERROR;
2230 // Mark the previously allocated bytes as free.
2231 memory_tracker_.TrackMemFree(bytes_allocated_);
2232 bytes_allocated_ = estimated_size;
2233 // Track the newly allocated bytes.
2234 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2239 void BackRenderbuffer::Destroy() {
2241 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2242 state_->GetErrorState());
2243 glDeleteRenderbuffersEXT(1, &id_);
2246 memory_tracker_.TrackMemFree(bytes_allocated_);
2247 bytes_allocated_ = 0;
2250 void BackRenderbuffer::Invalidate() {
2254 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2255 : decoder_(decoder),
2259 BackFramebuffer::~BackFramebuffer() {
2260 // This does not destroy the frame buffer because that would require that
2261 // the associated GL context was current. Just check that it was explicitly
2266 void BackFramebuffer::Create() {
2267 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2268 decoder_->GetErrorState());
2270 glGenFramebuffersEXT(1, &id_);
2273 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2275 ScopedGLErrorSuppressor suppressor(
2276 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2277 ScopedFrameBufferBinder binder(decoder_, id_);
2278 GLuint attach_id = texture ? texture->id() : 0;
2279 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2280 GL_COLOR_ATTACHMENT0,
2286 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2287 BackRenderbuffer* render_buffer) {
2289 ScopedGLErrorSuppressor suppressor(
2290 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2291 ScopedFrameBufferBinder binder(decoder_, id_);
2292 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2293 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2299 void BackFramebuffer::Destroy() {
2301 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2302 decoder_->GetErrorState());
2303 glDeleteFramebuffersEXT(1, &id_);
2308 void BackFramebuffer::Invalidate() {
2312 GLenum BackFramebuffer::CheckStatus() {
2314 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2315 decoder_->GetErrorState());
2316 ScopedFrameBufferBinder binder(decoder_, id_);
2317 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2320 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2321 return new GLES2DecoderImpl(group);
2324 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2327 logger_(&debug_marker_manager_),
2328 state_(group_->feature_info(), this, &logger_),
2329 unpack_flip_y_(false),
2330 unpack_premultiply_alpha_(false),
2331 unpack_unpremultiply_alpha_(false),
2332 attrib_0_buffer_id_(0),
2333 attrib_0_buffer_matches_value_(true),
2335 fixed_attrib_buffer_id_(0),
2336 fixed_attrib_buffer_size_(0),
2337 offscreen_target_color_format_(0),
2338 offscreen_target_depth_format_(0),
2339 offscreen_target_stencil_format_(0),
2340 offscreen_target_samples_(0),
2341 offscreen_target_buffer_preserved_(true),
2342 offscreen_saved_color_format_(0),
2343 back_buffer_color_format_(0),
2344 back_buffer_has_depth_(false),
2345 back_buffer_has_stencil_(false),
2346 surfaceless_(false),
2347 backbuffer_needs_clear_bits_(0),
2348 current_decoder_error_(error::kNoError),
2349 use_shader_translator_(true),
2350 validators_(group_->feature_info()->validators()),
2351 feature_info_(group_->feature_info()),
2353 has_robustness_extension_(false),
2354 reset_status_(GL_NO_ERROR),
2355 reset_by_robustness_extension_(false),
2356 supports_post_sub_buffer_(false),
2357 force_webgl_glsl_validation_(false),
2358 derivatives_explicitly_enabled_(false),
2359 frag_depth_explicitly_enabled_(false),
2360 draw_buffers_explicitly_enabled_(false),
2361 shader_texture_lod_explicitly_enabled_(false),
2362 compile_shader_always_succeeds_(false),
2363 lose_context_when_out_of_memory_(false),
2364 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2365 switches::kEnableGPUServiceLoggingGPU)),
2366 viewport_max_width_(0),
2367 viewport_max_height_(0),
2368 texture_state_(group_->feature_info()
2370 .texsubimage2d_faster_than_teximage2d),
2371 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2372 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2373 gpu_trace_level_(2),
2374 gpu_trace_commands_(false),
2375 gpu_debug_commands_(false),
2376 validation_texture_(0),
2377 validation_fbo_multisample_(0),
2378 validation_fbo_(0) {
2381 attrib_0_value_.v[0] = 0.0f;
2382 attrib_0_value_.v[1] = 0.0f;
2383 attrib_0_value_.v[2] = 0.0f;
2384 attrib_0_value_.v[3] = 1.0f;
2386 // The shader translator is used for WebGL even when running on EGL
2387 // because additional restrictions are needed (like only enabling
2388 // GL_OES_standard_derivatives on demand). It is used for the unit
2389 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2390 // the empty string to CompileShader and this is not a valid shader.
2391 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2392 CommandLine::ForCurrentProcess()->HasSwitch(
2393 switches::kDisableGLSLTranslator)) {
2394 use_shader_translator_ = false;
2398 GLES2DecoderImpl::~GLES2DecoderImpl() {
2401 bool GLES2DecoderImpl::Initialize(
2402 const scoped_refptr<gfx::GLSurface>& surface,
2403 const scoped_refptr<gfx::GLContext>& context,
2405 const gfx::Size& size,
2406 const DisallowedFeatures& disallowed_features,
2407 const std::vector<int32>& attribs) {
2408 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2409 DCHECK(context->IsCurrent(surface.get()));
2410 DCHECK(!context_.get());
2412 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2415 gpu_tracer_.reset(new GPUTracer(this));
2416 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2418 if (CommandLine::ForCurrentProcess()->HasSwitch(
2419 switches::kEnableGPUDebugging)) {
2423 if (CommandLine::ForCurrentProcess()->HasSwitch(
2424 switches::kEnableGPUCommandLogging)) {
2425 set_log_commands(true);
2428 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2429 switches::kCompileShaderAlwaysSucceeds);
2432 // Take ownership of the context and surface. The surface can be replaced with
2437 ContextCreationAttribHelper attrib_parser;
2438 if (!attrib_parser.Parse(attribs))
2441 // Save the loseContextWhenOutOfMemory context creation attribute.
2442 lose_context_when_out_of_memory_ =
2443 attrib_parser.lose_context_when_out_of_memory;
2445 // If the failIfMajorPerformanceCaveat context creation attribute was true
2446 // and we are using a software renderer, fail.
2447 if (attrib_parser.fail_if_major_perf_caveat &&
2448 feature_info_->feature_flags().is_swiftshader) {
2449 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2454 if (!group_->Initialize(this, disallowed_features)) {
2455 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2456 << "failed to initialize.";
2457 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2463 disallowed_features_ = disallowed_features;
2465 state_.attrib_values.resize(group_->max_vertex_attribs());
2466 vertex_array_manager_.reset(new VertexArrayManager());
2468 GLuint default_vertex_attrib_service_id = 0;
2469 if (features().native_vertex_array_object) {
2470 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2471 glBindVertexArrayOES(default_vertex_attrib_service_id);
2474 state_.default_vertex_attrib_manager =
2475 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2477 state_.default_vertex_attrib_manager->Initialize(
2478 group_->max_vertex_attribs(),
2479 feature_info_->workarounds().init_vertex_attributes);
2481 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2482 DoBindVertexArrayOES(0);
2484 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2486 image_manager_.reset(new ImageManager);
2488 util_.set_num_compressed_texture_formats(
2489 validators_->compressed_texture_format.GetValues().size());
2491 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2492 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2493 // OpenGL ES 2.0 does not have this issue.
2494 glEnableVertexAttribArray(0);
2496 glGenBuffersARB(1, &attrib_0_buffer_id_);
2497 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2498 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2499 glBindBuffer(GL_ARRAY_BUFFER, 0);
2500 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2502 state_.texture_units.resize(group_->max_texture_units());
2503 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2504 glActiveTexture(GL_TEXTURE0 + tt);
2505 // We want the last bind to be 2D.
2507 if (features().oes_egl_image_external) {
2508 ref = texture_manager()->GetDefaultTextureInfo(
2509 GL_TEXTURE_EXTERNAL_OES);
2510 state_.texture_units[tt].bound_texture_external_oes = ref;
2511 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2513 if (features().arb_texture_rectangle) {
2514 ref = texture_manager()->GetDefaultTextureInfo(
2515 GL_TEXTURE_RECTANGLE_ARB);
2516 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2517 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2519 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2520 state_.texture_units[tt].bound_texture_cube_map = ref;
2521 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2522 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2523 state_.texture_units[tt].bound_texture_2d = ref;
2524 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2526 glActiveTexture(GL_TEXTURE0);
2530 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2531 features().chromium_framebuffer_multisample) {
2532 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2533 // max_sample_count must be initialized to a sane value. If
2534 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2535 GLint max_sample_count = 1;
2536 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2537 offscreen_target_samples_ = std::min(attrib_parser.samples,
2540 offscreen_target_samples_ = 1;
2542 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2544 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2545 const bool rgb8_supported =
2546 context_->HasExtension("GL_OES_rgb8_rgba8");
2547 // The only available default render buffer formats in GLES2 have very
2548 // little precision. Don't enable multisampling unless 8-bit render
2549 // buffer formats are available--instead fall back to 8-bit textures.
2550 if (rgb8_supported && offscreen_target_samples_ > 1) {
2551 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2554 offscreen_target_samples_ = 1;
2555 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2559 // ANGLE only supports packed depth/stencil formats, so use it if it is
2561 const bool depth24_stencil8_supported =
2562 feature_info_->feature_flags().packed_depth24_stencil8;
2563 VLOG(1) << "GL_OES_packed_depth_stencil "
2564 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2565 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2566 depth24_stencil8_supported) {
2567 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2568 offscreen_target_stencil_format_ = 0;
2570 // It may be the case that this depth/stencil combination is not
2571 // supported, but this will be checked later by CheckFramebufferStatus.
2572 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2573 GL_DEPTH_COMPONENT16 : 0;
2574 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2575 GL_STENCIL_INDEX8 : 0;
2578 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2581 // If depth is requested at all, use the packed depth stencil format if
2582 // it's available, as some desktop GL drivers don't support any non-packed
2583 // formats for depth attachments.
2584 const bool depth24_stencil8_supported =
2585 feature_info_->feature_flags().packed_depth24_stencil8;
2586 VLOG(1) << "GL_EXT_packed_depth_stencil "
2587 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2589 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2590 depth24_stencil8_supported) {
2591 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2592 offscreen_target_stencil_format_ = 0;
2594 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2595 GL_DEPTH_COMPONENT : 0;
2596 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2597 GL_STENCIL_INDEX : 0;
2601 offscreen_saved_color_format_ = attrib_parser.alpha_size > 0 ?
2604 // Create the target frame buffer. This is the one that the client renders
2606 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2607 offscreen_target_frame_buffer_->Create();
2608 // Due to GLES2 format limitations, either the color texture (for
2609 // non-multisampling) or the color render buffer (for multisampling) will be
2610 // attached to the offscreen frame buffer. The render buffer has more
2611 // limited formats available to it, but the texture can't do multisampling.
2612 if (IsOffscreenBufferMultisampled()) {
2613 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2614 renderbuffer_manager(), memory_tracker(), &state_));
2615 offscreen_target_color_render_buffer_->Create();
2617 offscreen_target_color_texture_.reset(new BackTexture(
2618 memory_tracker(), &state_));
2619 offscreen_target_color_texture_->Create();
2621 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2622 renderbuffer_manager(), memory_tracker(), &state_));
2623 offscreen_target_depth_render_buffer_->Create();
2624 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2625 renderbuffer_manager(), memory_tracker(), &state_));
2626 offscreen_target_stencil_render_buffer_->Create();
2628 // Create the saved offscreen texture. The target frame buffer is copied
2629 // here when SwapBuffers is called.
2630 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2631 offscreen_saved_frame_buffer_->Create();
2633 offscreen_saved_color_texture_.reset(new BackTexture(
2634 memory_tracker(), &state_));
2635 offscreen_saved_color_texture_->Create();
2637 // Allocate the render buffers at their initial size and check the status
2638 // of the frame buffers is okay.
2639 if (!ResizeOffscreenFrameBuffer(size)) {
2640 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2645 // Allocate the offscreen saved color texture.
2646 DCHECK(offscreen_saved_color_format_);
2647 offscreen_saved_color_texture_->AllocateStorage(
2648 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2650 offscreen_saved_frame_buffer_->AttachRenderTexture(
2651 offscreen_saved_color_texture_.get());
2652 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2653 GL_FRAMEBUFFER_COMPLETE) {
2654 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2659 // Bind to the new default frame buffer (the offscreen target frame buffer).
2660 // This should now be associated with ID zero.
2661 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2663 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2664 // These are NOT if the back buffer has these proprorties. They are
2665 // if we want the command buffer to enforce them regardless of what
2666 // the real backbuffer is assuming the real back buffer gives us more than
2667 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2668 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2669 // can't do anything about that.
2671 if (!surfaceless_) {
2673 glGetIntegerv(GL_ALPHA_BITS, &v);
2674 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2675 // the user requested RGB then RGB. If the user did not specify a
2676 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2677 back_buffer_color_format_ =
2678 (attrib_parser.alpha_size != 0 && v > 0) ? GL_RGBA : GL_RGB;
2679 glGetIntegerv(GL_DEPTH_BITS, &v);
2680 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && v > 0;
2681 glGetIntegerv(GL_STENCIL_BITS, &v);
2682 back_buffer_has_stencil_ = attrib_parser.stencil_size != 0 && v > 0;
2686 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2687 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2688 // isn't well documented; it was discovered in the Khronos OpenGL ES
2689 // mailing list archives. It also implicitly enables the desktop GL
2690 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2691 // variable in fragment shaders.
2692 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2693 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2694 glEnable(GL_POINT_SPRITE);
2697 has_robustness_extension_ =
2698 context->HasExtension("GL_ARB_robustness") ||
2699 context->HasExtension("GL_KHR_robustness") ||
2700 context->HasExtension("GL_EXT_robustness");
2702 if (!InitializeShaderTranslator()) {
2706 state_.viewport_width = size.width();
2707 state_.viewport_height = size.height();
2709 GLint viewport_params[4] = { 0 };
2710 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2711 viewport_max_width_ = viewport_params[0];
2712 viewport_max_height_ = viewport_params[1];
2714 state_.scissor_width = state_.viewport_width;
2715 state_.scissor_height = state_.viewport_height;
2717 // Set all the default state because some GL drivers get it wrong.
2718 state_.InitCapabilities(NULL);
2719 state_.InitState(NULL);
2720 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2722 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2723 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2724 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2725 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2726 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2728 bool call_gl_clear = !surfaceless_;
2729 #if defined(OS_ANDROID)
2730 // Temporary workaround for Android WebView because this clear ignores the
2731 // clip and corrupts that external UI of the App. Not calling glClear is ok
2732 // because the system already clears the buffer before each draw. Proper
2733 // fix might be setting the scissor clip properly before initialize. See
2734 // crbug.com/259023 for details.
2735 call_gl_clear = surface_->GetHandle();
2737 if (call_gl_clear) {
2738 // Clear the backbuffer.
2739 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2742 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2743 if (feature_info_->workarounds()
2744 .disable_post_sub_buffers_for_onscreen_surfaces &&
2745 !surface->IsOffscreen())
2746 supports_post_sub_buffer_ = false;
2748 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2749 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2752 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2753 context_->SetUnbindFboOnMakeCurrent();
2756 // Only compositor contexts are known to use only the subset of GL
2757 // that can be safely migrated between the iGPU and the dGPU. Mark
2758 // those contexts as safe to forcibly transition between the GPUs.
2759 // http://crbug.com/180876, http://crbug.com/227228
2761 context_->SetSafeToForceGpuSwitch();
2763 async_pixel_transfer_manager_.reset(
2764 AsyncPixelTransferManager::Create(context.get()));
2765 async_pixel_transfer_manager_->Initialize(texture_manager());
2767 framebuffer_manager()->AddObserver(this);
2772 Capabilities GLES2DecoderImpl::GetCapabilities() {
2773 DCHECK(initialized());
2777 caps.egl_image_external =
2778 feature_info_->feature_flags().oes_egl_image_external;
2779 caps.texture_format_bgra8888 =
2780 feature_info_->feature_flags().ext_texture_format_bgra8888;
2781 caps.texture_format_etc1 =
2782 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2783 caps.texture_format_etc1_npot =
2784 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
2785 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2786 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2787 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2788 caps.discard_framebuffer =
2789 feature_info_->feature_flags().ext_discard_framebuffer;
2790 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2792 #if defined(OS_MACOSX)
2793 // This is unconditionally true on mac, no need to test for it at runtime.
2794 caps.iosurface = true;
2797 caps.post_sub_buffer = supports_post_sub_buffer_;
2800 caps.blend_equation_advanced =
2801 feature_info_->feature_flags().blend_equation_advanced;
2802 caps.blend_equation_advanced_coherent =
2803 feature_info_->feature_flags().blend_equation_advanced_coherent;
2807 void GLES2DecoderImpl::UpdateCapabilities() {
2808 util_.set_num_compressed_texture_formats(
2809 validators_->compressed_texture_format.GetValues().size());
2810 util_.set_num_shader_binary_formats(
2811 validators_->shader_binary_format.GetValues().size());
2814 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2815 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2817 if (!use_shader_translator_) {
2820 ShBuiltInResources resources;
2821 ShInitBuiltInResources(&resources);
2822 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2823 resources.MaxVertexUniformVectors =
2824 group_->max_vertex_uniform_vectors();
2825 resources.MaxVaryingVectors = group_->max_varying_vectors();
2826 resources.MaxVertexTextureImageUnits =
2827 group_->max_vertex_texture_image_units();
2828 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2829 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2830 resources.MaxFragmentUniformVectors =
2831 group_->max_fragment_uniform_vectors();
2832 resources.MaxDrawBuffers = group_->max_draw_buffers();
2833 resources.MaxExpressionComplexity = 256;
2834 resources.MaxCallStackDepth = 256;
2836 GLint range[2] = { 0, 0 };
2837 GLint precision = 0;
2838 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2840 resources.FragmentPrecisionHigh =
2841 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2843 if (force_webgl_glsl_validation_) {
2844 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2845 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2846 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2847 if (!draw_buffers_explicitly_enabled_)
2848 resources.MaxDrawBuffers = 1;
2849 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2850 resources.NV_draw_buffers =
2851 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
2853 resources.OES_standard_derivatives =
2854 features().oes_standard_derivatives ? 1 : 0;
2855 resources.ARB_texture_rectangle =
2856 features().arb_texture_rectangle ? 1 : 0;
2857 resources.OES_EGL_image_external =
2858 features().oes_egl_image_external ? 1 : 0;
2859 resources.EXT_draw_buffers =
2860 features().ext_draw_buffers ? 1 : 0;
2861 resources.EXT_frag_depth =
2862 features().ext_frag_depth ? 1 : 0;
2863 resources.EXT_shader_texture_lod =
2864 features().ext_shader_texture_lod ? 1 : 0;
2865 resources.NV_draw_buffers =
2866 features().nv_draw_buffers ? 1 : 0;
2869 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2871 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2872 resources.HashFunction = &CityHash64;
2874 resources.HashFunction = NULL;
2875 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2876 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2877 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2878 int driver_bug_workarounds = 0;
2879 if (workarounds().needs_glsl_built_in_function_emulation)
2880 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2881 if (workarounds().init_gl_position_in_vertex_shader)
2882 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2883 if (workarounds().unfold_short_circuit_as_ternary_operation)
2884 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2885 if (workarounds().init_varyings_without_static_use)
2886 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2887 if (workarounds().unroll_for_loop_with_sampler_array_index)
2888 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2889 if (workarounds().scalarize_vec_and_mat_constructor_args)
2890 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
2891 if (workarounds().regenerate_struct_names)
2892 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
2894 vertex_translator_ = shader_translator_cache()->GetTranslator(
2898 implementation_type,
2899 static_cast<ShCompileOptions>(driver_bug_workarounds));
2900 if (!vertex_translator_.get()) {
2901 LOG(ERROR) << "Could not initialize vertex shader translator.";
2906 fragment_translator_ = shader_translator_cache()->GetTranslator(
2910 implementation_type,
2911 static_cast<ShCompileOptions>(driver_bug_workarounds));
2912 if (!fragment_translator_.get()) {
2913 LOG(ERROR) << "Could not initialize fragment shader translator.";
2920 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2921 for (GLsizei ii = 0; ii < n; ++ii) {
2922 if (GetBuffer(client_ids[ii])) {
2926 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2927 glGenBuffersARB(n, service_ids.get());
2928 for (GLsizei ii = 0; ii < n; ++ii) {
2929 CreateBuffer(client_ids[ii], service_ids[ii]);
2934 bool GLES2DecoderImpl::GenFramebuffersHelper(
2935 GLsizei n, const GLuint* client_ids) {
2936 for (GLsizei ii = 0; ii < n; ++ii) {
2937 if (GetFramebuffer(client_ids[ii])) {
2941 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2942 glGenFramebuffersEXT(n, service_ids.get());
2943 for (GLsizei ii = 0; ii < n; ++ii) {
2944 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2949 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2950 GLsizei n, const GLuint* client_ids) {
2951 for (GLsizei ii = 0; ii < n; ++ii) {
2952 if (GetRenderbuffer(client_ids[ii])) {
2956 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2957 glGenRenderbuffersEXT(n, service_ids.get());
2958 for (GLsizei ii = 0; ii < n; ++ii) {
2959 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2964 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
2965 const GLuint* client_ids) {
2966 for (GLsizei ii = 0; ii < n; ++ii) {
2967 if (GetValuebuffer(client_ids[ii])) {
2971 for (GLsizei ii = 0; ii < n; ++ii) {
2972 CreateValuebuffer(client_ids[ii]);
2977 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2978 for (GLsizei ii = 0; ii < n; ++ii) {
2979 if (GetTexture(client_ids[ii])) {
2983 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2984 glGenTextures(n, service_ids.get());
2985 for (GLsizei ii = 0; ii < n; ++ii) {
2986 CreateTexture(client_ids[ii], service_ids[ii]);
2991 void GLES2DecoderImpl::DeleteBuffersHelper(
2992 GLsizei n, const GLuint* client_ids) {
2993 for (GLsizei ii = 0; ii < n; ++ii) {
2994 Buffer* buffer = GetBuffer(client_ids[ii]);
2995 if (buffer && !buffer->IsDeleted()) {
2996 state_.vertex_attrib_manager->Unbind(buffer);
2997 if (state_.bound_array_buffer.get() == buffer) {
2998 state_.bound_array_buffer = NULL;
3000 RemoveBuffer(client_ids[ii]);
3005 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3006 GLsizei n, const GLuint* client_ids) {
3007 bool supports_separate_framebuffer_binds =
3008 features().chromium_framebuffer_multisample;
3010 for (GLsizei ii = 0; ii < n; ++ii) {
3011 Framebuffer* framebuffer =
3012 GetFramebuffer(client_ids[ii]);
3013 if (framebuffer && !framebuffer->IsDeleted()) {
3014 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3015 framebuffer_state_.bound_draw_framebuffer = NULL;
3016 framebuffer_state_.clear_state_dirty = true;
3017 GLenum target = supports_separate_framebuffer_binds ?
3018 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3019 glBindFramebufferEXT(target, GetBackbufferServiceId());
3021 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3022 framebuffer_state_.bound_read_framebuffer = NULL;
3023 GLenum target = supports_separate_framebuffer_binds ?
3024 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3025 glBindFramebufferEXT(target, GetBackbufferServiceId());
3028 RemoveFramebuffer(client_ids[ii]);
3033 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3034 GLsizei n, const GLuint* client_ids) {
3035 bool supports_separate_framebuffer_binds =
3036 features().chromium_framebuffer_multisample;
3037 for (GLsizei ii = 0; ii < n; ++ii) {
3038 Renderbuffer* renderbuffer =
3039 GetRenderbuffer(client_ids[ii]);
3040 if (renderbuffer && !renderbuffer->IsDeleted()) {
3041 if (state_.bound_renderbuffer.get() == renderbuffer) {
3042 state_.bound_renderbuffer = NULL;
3044 // Unbind from current framebuffers.
3045 if (supports_separate_framebuffer_binds) {
3046 if (framebuffer_state_.bound_read_framebuffer.get()) {
3047 framebuffer_state_.bound_read_framebuffer
3048 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3050 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3051 framebuffer_state_.bound_draw_framebuffer
3052 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3055 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3056 framebuffer_state_.bound_draw_framebuffer
3057 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3060 framebuffer_state_.clear_state_dirty = true;
3061 RemoveRenderbuffer(client_ids[ii]);
3066 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3068 const GLuint* client_ids) {
3069 for (GLsizei ii = 0; ii < n; ++ii) {
3070 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3072 if (state_.bound_valuebuffer.get() == valuebuffer) {
3073 state_.bound_valuebuffer = NULL;
3075 RemoveValuebuffer(client_ids[ii]);
3080 void GLES2DecoderImpl::DeleteTexturesHelper(
3081 GLsizei n, const GLuint* client_ids) {
3082 bool supports_separate_framebuffer_binds =
3083 features().chromium_framebuffer_multisample;
3084 for (GLsizei ii = 0; ii < n; ++ii) {
3085 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3087 Texture* texture = texture_ref->texture();
3088 if (texture->IsAttachedToFramebuffer()) {
3089 framebuffer_state_.clear_state_dirty = true;
3091 // Unbind texture_ref from texture_ref units.
3092 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3093 state_.texture_units[jj].Unbind(texture_ref);
3095 // Unbind from current framebuffers.
3096 if (supports_separate_framebuffer_binds) {
3097 if (framebuffer_state_.bound_read_framebuffer.get()) {
3098 framebuffer_state_.bound_read_framebuffer
3099 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3101 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3102 framebuffer_state_.bound_draw_framebuffer
3103 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3106 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3107 framebuffer_state_.bound_draw_framebuffer
3108 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3111 #if defined(OS_MACOSX)
3112 GLuint service_id = texture->service_id();
3113 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3114 ReleaseIOSurfaceForTexture(service_id);
3117 RemoveTexture(client_ids[ii]);
3122 // } // anonymous namespace
3124 bool GLES2DecoderImpl::MakeCurrent() {
3125 if (!context_.get())
3128 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
3129 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3131 MaybeExitOnContextLost();
3136 ProcessFinishedAsyncTransfers();
3138 // Rebind the FBO if it was unbound by the context.
3139 if (workarounds().unbind_fbo_on_context_switch)
3140 RestoreFramebufferBindings();
3142 framebuffer_state_.clear_state_dirty = true;
3147 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3148 ProcessPendingReadPixels();
3149 if (engine() && query_manager_.get())
3150 query_manager_->ProcessPendingTransferQueries();
3152 // TODO(epenner): Is there a better place to do this?
3153 // This needs to occur before we execute any batch of commands
3154 // from the client, as the client may have recieved an async
3155 // completion while issuing those commands.
3156 // "DidFlushStart" would be ideal if we had such a callback.
3157 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3160 static void RebindCurrentFramebuffer(
3162 Framebuffer* framebuffer,
3163 GLuint back_buffer_service_id) {
3164 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3166 if (framebuffer_id == 0) {
3167 framebuffer_id = back_buffer_service_id;
3170 glBindFramebufferEXT(target, framebuffer_id);
3173 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3174 framebuffer_state_.clear_state_dirty = true;
3176 if (!features().chromium_framebuffer_multisample) {
3177 RebindCurrentFramebuffer(
3179 framebuffer_state_.bound_draw_framebuffer.get(),
3180 GetBackbufferServiceId());
3182 RebindCurrentFramebuffer(
3183 GL_READ_FRAMEBUFFER_EXT,
3184 framebuffer_state_.bound_read_framebuffer.get(),
3185 GetBackbufferServiceId());
3186 RebindCurrentFramebuffer(
3187 GL_DRAW_FRAMEBUFFER_EXT,
3188 framebuffer_state_.bound_draw_framebuffer.get(),
3189 GetBackbufferServiceId());
3194 bool GLES2DecoderImpl::CheckFramebufferValid(
3195 Framebuffer* framebuffer,
3196 GLenum target, const char* func_name) {
3200 if (backbuffer_needs_clear_bits_) {
3201 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3202 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3203 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3205 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3206 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3208 state_.SetDeviceDepthMask(GL_TRUE);
3209 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3210 bool reset_draw_buffer = false;
3211 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3212 group_->draw_buffer() == GL_NONE) {
3213 reset_draw_buffer = true;
3214 GLenum buf = GL_BACK;
3215 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3216 buf = GL_COLOR_ATTACHMENT0;
3217 glDrawBuffersARB(1, &buf);
3219 glClear(backbuffer_needs_clear_bits_);
3220 if (reset_draw_buffer) {
3221 GLenum buf = GL_NONE;
3222 glDrawBuffersARB(1, &buf);
3224 backbuffer_needs_clear_bits_ = 0;
3225 RestoreClearState();
3230 if (framebuffer_manager()->IsComplete(framebuffer)) {
3234 GLenum completeness = framebuffer->IsPossiblyComplete();
3235 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3237 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3241 // Are all the attachments cleared?
3242 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3243 texture_manager()->HaveUnclearedMips()) {
3244 if (!framebuffer->IsCleared()) {
3245 // Can we clear them?
3246 if (framebuffer->GetStatus(texture_manager(), target) !=
3247 GL_FRAMEBUFFER_COMPLETE) {
3249 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3250 "framebuffer incomplete (clear)");
3253 ClearUnclearedAttachments(target, framebuffer);
3257 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3258 if (framebuffer->GetStatus(texture_manager(), target) !=
3259 GL_FRAMEBUFFER_COMPLETE) {
3261 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3262 "framebuffer incomplete (check)");
3265 framebuffer_manager()->MarkAsComplete(framebuffer);
3268 // NOTE: At this point we don't know if the framebuffer is complete but
3269 // we DO know that everything that needs to be cleared has been cleared.
3273 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3274 if (!features().chromium_framebuffer_multisample) {
3275 bool valid = CheckFramebufferValid(
3276 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3284 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3285 GL_DRAW_FRAMEBUFFER_EXT,
3287 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3288 GL_READ_FRAMEBUFFER_EXT,
3292 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3293 const char* func_name) {
3294 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3295 framebuffer_state_.bound_read_framebuffer.get() :
3296 framebuffer_state_.bound_draw_framebuffer.get();
3299 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3301 GL_INVALID_OPERATION, func_name, "no color image attached");
3307 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3308 TextureRef* texture, GLint level) {
3309 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3310 framebuffer_state_.bound_read_framebuffer.get() :
3311 framebuffer_state_.bound_draw_framebuffer.get();
3314 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3315 GL_COLOR_ATTACHMENT0);
3318 return attachment->FormsFeedbackLoop(texture, level);
3321 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3322 Framebuffer* framebuffer =
3323 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3324 if (framebuffer != NULL) {
3325 const Framebuffer::Attachment* attachment =
3326 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3328 return gfx::Size(attachment->width(), attachment->height());
3330 return gfx::Size(0, 0);
3331 } else if (offscreen_target_frame_buffer_.get()) {
3332 return offscreen_size_;
3334 return surface_->GetSize();
3338 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3339 Framebuffer* framebuffer =
3340 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3341 if (framebuffer != NULL) {
3342 return framebuffer->GetColorAttachmentTextureType();
3344 return GL_UNSIGNED_BYTE;
3348 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3349 Framebuffer* framebuffer =
3350 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3351 if (framebuffer != NULL) {
3352 return framebuffer->GetColorAttachmentFormat();
3353 } else if (offscreen_target_frame_buffer_.get()) {
3354 return offscreen_target_color_format_;
3356 return back_buffer_color_format_;
3360 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3361 Framebuffer* framebuffer =
3362 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3363 if (framebuffer != NULL) {
3364 return framebuffer->GetColorAttachmentFormat();
3365 } else if (offscreen_target_frame_buffer_.get()) {
3366 return offscreen_target_color_format_;
3368 return back_buffer_color_format_;
3372 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3373 if (!offscreen_saved_color_texture_info_.get())
3375 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3376 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3377 texture_manager()->SetLevelInfo(
3378 offscreen_saved_color_texture_info_.get(),
3382 offscreen_size_.width(),
3383 offscreen_size_.height(),
3389 texture_manager()->SetParameteri(
3390 "UpdateParentTextureInfo",
3392 offscreen_saved_color_texture_info_.get(),
3393 GL_TEXTURE_MAG_FILTER,
3395 texture_manager()->SetParameteri(
3396 "UpdateParentTextureInfo",
3398 offscreen_saved_color_texture_info_.get(),
3399 GL_TEXTURE_MIN_FILTER,
3401 texture_manager()->SetParameteri(
3402 "UpdateParentTextureInfo",
3404 offscreen_saved_color_texture_info_.get(),
3407 texture_manager()->SetParameteri(
3408 "UpdateParentTextureInfo",
3410 offscreen_saved_color_texture_info_.get(),
3413 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3415 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3418 void GLES2DecoderImpl::SetResizeCallback(
3419 const base::Callback<void(gfx::Size, float)>& callback) {
3420 resize_callback_ = callback;
3423 Logger* GLES2DecoderImpl::GetLogger() {
3427 void GLES2DecoderImpl::BeginDecoding() {
3428 gpu_tracer_->BeginDecoding();
3429 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3430 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3431 (*cb_command_trace_category_ != 0);
3434 void GLES2DecoderImpl::EndDecoding() {
3435 gpu_tracer_->EndDecoding();
3438 ErrorState* GLES2DecoderImpl::GetErrorState() {
3439 return state_.GetErrorState();
3442 void GLES2DecoderImpl::SetShaderCacheCallback(
3443 const ShaderCacheCallback& callback) {
3444 shader_cache_callback_ = callback;
3447 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3448 const WaitSyncPointCallback& callback) {
3449 wait_sync_point_callback_ = callback;
3452 AsyncPixelTransferManager*
3453 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3454 return async_pixel_transfer_manager_.get();
3457 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3458 async_pixel_transfer_manager_.reset();
3461 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3462 AsyncPixelTransferManager* manager) {
3463 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3466 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3467 uint32* service_texture_id) {
3468 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3470 *service_texture_id = texture_ref->service_id();
3476 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3477 return texture_state_.texture_upload_count +
3478 async_pixel_transfer_manager_->GetTextureUploadCount();
3481 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3482 return texture_state_.total_texture_upload_time +
3483 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3486 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3487 return total_processing_commands_time_;
3490 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3491 total_processing_commands_time_ += time;
3494 void GLES2DecoderImpl::Destroy(bool have_context) {
3498 DCHECK(!have_context || context_->IsCurrent(NULL));
3500 // Unbind everything.
3501 state_.vertex_attrib_manager = NULL;
3502 state_.default_vertex_attrib_manager = NULL;
3503 state_.texture_units.clear();
3504 state_.bound_array_buffer = NULL;
3505 state_.current_queries.clear();
3506 framebuffer_state_.bound_read_framebuffer = NULL;
3507 framebuffer_state_.bound_draw_framebuffer = NULL;
3508 state_.bound_renderbuffer = NULL;
3509 state_.bound_valuebuffer = NULL;
3511 if (offscreen_saved_color_texture_info_.get()) {
3512 DCHECK(offscreen_target_color_texture_);
3513 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3514 offscreen_saved_color_texture_->id());
3515 offscreen_saved_color_texture_->Invalidate();
3516 offscreen_saved_color_texture_info_ = NULL;
3519 if (copy_texture_CHROMIUM_.get()) {
3520 copy_texture_CHROMIUM_->Destroy();
3521 copy_texture_CHROMIUM_.reset();
3524 if (state_.current_program.get()) {
3525 program_manager()->UnuseProgram(shader_manager(),
3526 state_.current_program.get());
3529 if (attrib_0_buffer_id_) {
3530 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3532 if (fixed_attrib_buffer_id_) {
3533 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3536 if (validation_texture_) {
3537 glDeleteTextures(1, &validation_texture_);
3538 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3539 glDeleteFramebuffersEXT(1, &validation_fbo_);
3542 if (offscreen_target_frame_buffer_.get())
3543 offscreen_target_frame_buffer_->Destroy();
3544 if (offscreen_target_color_texture_.get())
3545 offscreen_target_color_texture_->Destroy();
3546 if (offscreen_target_color_render_buffer_.get())
3547 offscreen_target_color_render_buffer_->Destroy();
3548 if (offscreen_target_depth_render_buffer_.get())
3549 offscreen_target_depth_render_buffer_->Destroy();
3550 if (offscreen_target_stencil_render_buffer_.get())
3551 offscreen_target_stencil_render_buffer_->Destroy();
3552 if (offscreen_saved_frame_buffer_.get())
3553 offscreen_saved_frame_buffer_->Destroy();
3554 if (offscreen_saved_color_texture_.get())
3555 offscreen_saved_color_texture_->Destroy();
3556 if (offscreen_resolved_frame_buffer_.get())
3557 offscreen_resolved_frame_buffer_->Destroy();
3558 if (offscreen_resolved_color_texture_.get())
3559 offscreen_resolved_color_texture_->Destroy();
3561 if (offscreen_target_frame_buffer_.get())
3562 offscreen_target_frame_buffer_->Invalidate();
3563 if (offscreen_target_color_texture_.get())
3564 offscreen_target_color_texture_->Invalidate();
3565 if (offscreen_target_color_render_buffer_.get())
3566 offscreen_target_color_render_buffer_->Invalidate();
3567 if (offscreen_target_depth_render_buffer_.get())
3568 offscreen_target_depth_render_buffer_->Invalidate();
3569 if (offscreen_target_stencil_render_buffer_.get())
3570 offscreen_target_stencil_render_buffer_->Invalidate();
3571 if (offscreen_saved_frame_buffer_.get())
3572 offscreen_saved_frame_buffer_->Invalidate();
3573 if (offscreen_saved_color_texture_.get())
3574 offscreen_saved_color_texture_->Invalidate();
3575 if (offscreen_resolved_frame_buffer_.get())
3576 offscreen_resolved_frame_buffer_->Invalidate();
3577 if (offscreen_resolved_color_texture_.get())
3578 offscreen_resolved_color_texture_->Invalidate();
3581 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3582 // Otherwise, we can leak objects. http://crbug.com/258772.
3583 // state_.current_program must be reset before group_ is reset because
3584 // the later deletes the ProgramManager object that referred by
3585 // state_.current_program object.
3586 state_.current_program = NULL;
3588 copy_texture_CHROMIUM_.reset();
3590 if (query_manager_.get()) {
3591 query_manager_->Destroy(have_context);
3592 query_manager_.reset();
3595 if (vertex_array_manager_ .get()) {
3596 vertex_array_manager_->Destroy(have_context);
3597 vertex_array_manager_.reset();
3600 if (image_manager_.get()) {
3601 image_manager_->Destroy(have_context);
3602 image_manager_.reset();
3605 offscreen_target_frame_buffer_.reset();
3606 offscreen_target_color_texture_.reset();
3607 offscreen_target_color_render_buffer_.reset();
3608 offscreen_target_depth_render_buffer_.reset();
3609 offscreen_target_stencil_render_buffer_.reset();
3610 offscreen_saved_frame_buffer_.reset();
3611 offscreen_saved_color_texture_.reset();
3612 offscreen_resolved_frame_buffer_.reset();
3613 offscreen_resolved_color_texture_.reset();
3615 // Need to release these before releasing |group_| which may own the
3616 // ShaderTranslatorCache.
3617 fragment_translator_ = NULL;
3618 vertex_translator_ = NULL;
3620 // Should destroy the transfer manager before the texture manager held
3621 // by the context group.
3622 async_pixel_transfer_manager_.reset();
3625 framebuffer_manager()->RemoveObserver(this);
3626 group_->Destroy(this, have_context);
3630 if (context_.get()) {
3631 context_->ReleaseCurrent(NULL);
3635 #if defined(OS_MACOSX)
3636 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3637 it != texture_to_io_surface_map_.end(); ++it) {
3638 CFRelease(it->second);
3640 texture_to_io_surface_map_.clear();
3644 void GLES2DecoderImpl::SetSurface(
3645 const scoped_refptr<gfx::GLSurface>& surface) {
3646 DCHECK(context_->IsCurrent(NULL));
3647 DCHECK(surface_.get());
3649 RestoreCurrentFramebufferBindings();
3652 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3653 if (!offscreen_saved_color_texture_.get()) {
3654 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3657 if (!offscreen_saved_color_texture_info_.get()) {
3658 GLuint service_id = offscreen_saved_color_texture_->id();
3659 offscreen_saved_color_texture_info_ = TextureRef::Create(
3660 texture_manager(), 0, service_id);
3661 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3663 UpdateParentTextureInfo();
3665 mailbox_manager()->ProduceTexture(
3666 mailbox, offscreen_saved_color_texture_info_->texture());
3669 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3670 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3671 if (!is_offscreen) {
3672 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3673 << " with an onscreen framebuffer.";
3677 if (offscreen_size_ == size)
3680 offscreen_size_ = size;
3681 int w = offscreen_size_.width();
3682 int h = offscreen_size_.height();
3683 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3684 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3685 << "to allocate storage due to excessive dimensions.";
3689 // Reallocate the offscreen target buffers.
3690 DCHECK(offscreen_target_color_format_);
3691 if (IsOffscreenBufferMultisampled()) {
3692 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3693 feature_info_.get(),
3695 offscreen_target_color_format_,
3696 offscreen_target_samples_)) {
3697 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3698 << "to allocate storage for offscreen target color buffer.";
3702 if (!offscreen_target_color_texture_->AllocateStorage(
3703 offscreen_size_, offscreen_target_color_format_, false)) {
3704 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3705 << "to allocate storage for offscreen target color texture.";
3709 if (offscreen_target_depth_format_ &&
3710 !offscreen_target_depth_render_buffer_->AllocateStorage(
3711 feature_info_.get(),
3713 offscreen_target_depth_format_,
3714 offscreen_target_samples_)) {
3715 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3716 << "to allocate storage for offscreen target depth buffer.";
3719 if (offscreen_target_stencil_format_ &&
3720 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3721 feature_info_.get(),
3723 offscreen_target_stencil_format_,
3724 offscreen_target_samples_)) {
3725 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3726 << "to allocate storage for offscreen target stencil buffer.";
3730 // Attach the offscreen target buffers to the target frame buffer.
3731 if (IsOffscreenBufferMultisampled()) {
3732 offscreen_target_frame_buffer_->AttachRenderBuffer(
3733 GL_COLOR_ATTACHMENT0,
3734 offscreen_target_color_render_buffer_.get());
3736 offscreen_target_frame_buffer_->AttachRenderTexture(
3737 offscreen_target_color_texture_.get());
3739 if (offscreen_target_depth_format_) {
3740 offscreen_target_frame_buffer_->AttachRenderBuffer(
3741 GL_DEPTH_ATTACHMENT,
3742 offscreen_target_depth_render_buffer_.get());
3744 const bool packed_depth_stencil =
3745 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3746 if (packed_depth_stencil) {
3747 offscreen_target_frame_buffer_->AttachRenderBuffer(
3748 GL_STENCIL_ATTACHMENT,
3749 offscreen_target_depth_render_buffer_.get());
3750 } else if (offscreen_target_stencil_format_) {
3751 offscreen_target_frame_buffer_->AttachRenderBuffer(
3752 GL_STENCIL_ATTACHMENT,
3753 offscreen_target_stencil_render_buffer_.get());
3756 if (offscreen_target_frame_buffer_->CheckStatus() !=
3757 GL_FRAMEBUFFER_COMPLETE) {
3758 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3759 << "because offscreen FBO was incomplete.";
3763 // Clear the target frame buffer.
3765 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3766 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3767 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3768 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3770 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3771 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3773 state_.SetDeviceDepthMask(GL_TRUE);
3774 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3775 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3776 RestoreClearState();
3779 // Destroy the offscreen resolved framebuffers.
3780 if (offscreen_resolved_frame_buffer_.get())
3781 offscreen_resolved_frame_buffer_->Destroy();
3782 if (offscreen_resolved_color_texture_.get())
3783 offscreen_resolved_color_texture_->Destroy();
3784 offscreen_resolved_color_texture_.reset();
3785 offscreen_resolved_frame_buffer_.reset();
3790 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
3791 const void* cmd_data) {
3792 const gles2::cmds::ResizeCHROMIUM& c =
3793 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
3794 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3795 return error::kDeferCommandUntilLater;
3797 GLuint width = static_cast<GLuint>(c.width);
3798 GLuint height = static_cast<GLuint>(c.height);
3799 GLfloat scale_factor = c.scale_factor;
3800 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3802 width = std::max(1U, width);
3803 height = std::max(1U, height);
3805 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3806 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3807 // Make sure that we are done drawing to the back buffer before resizing.
3810 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3812 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3813 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3814 << "ResizeOffscreenFrameBuffer failed.";
3815 return error::kLostContext;
3819 if (!resize_callback_.is_null()) {
3820 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3821 DCHECK(context_->IsCurrent(surface_.get()));
3822 if (!context_->IsCurrent(surface_.get())) {
3823 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3824 << "current after resize callback.";
3825 return error::kLostContext;
3829 return error::kNoError;
3832 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3833 if (command_id > kStartPoint && command_id < kNumCommands) {
3834 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3836 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3839 // Decode a command, and call the corresponding GL functions.
3840 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
3841 // of commands at once, and is now only used for tests that need to track
3842 // individual commands.
3843 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
3844 unsigned int arg_count,
3845 const void* cmd_data) {
3846 return DoCommands(1, cmd_data, arg_count + 1, 0);
3849 // Decode multiple commands, and call the corresponding GL functions.
3850 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
3851 // changed by a (malicious) client at any time, so if validation has to happen,
3852 // it should operate on a copy of them.
3853 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
3854 // interest of performance in this critical execution loop.
3855 template <bool DebugImpl>
3856 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
3859 int* entries_processed) {
3860 commands_to_process_ = num_commands;
3861 error::Error result = error::kNoError;
3862 const CommandBufferEntry* cmd_data =
3863 static_cast<const CommandBufferEntry*>(buffer);
3864 int process_pos = 0;
3865 unsigned int command = 0;
3867 while (process_pos < num_entries && result == error::kNoError &&
3868 commands_to_process_--) {
3869 const unsigned int size = cmd_data->value_header.size;
3870 command = cmd_data->value_header.command;
3873 result = error::kInvalidSize;
3877 if (static_cast<int>(size) + process_pos > num_entries) {
3878 result = error::kOutOfBounds;
3883 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3884 GetCommandName(command));
3886 if (log_commands()) {
3887 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
3888 << "cmd: " << GetCommandName(command);
3892 const unsigned int arg_count = size - 1;
3893 unsigned int command_index = command - kStartPoint - 1;
3894 if (command_index < arraysize(command_info)) {
3895 const CommandInfo& info = command_info[command_index];
3896 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3897 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3898 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3899 bool doing_gpu_trace = false;
3900 if (DebugImpl && gpu_trace_commands_) {
3901 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3902 doing_gpu_trace = true;
3903 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3907 uint32 immediate_data_size = (arg_count - info_arg_count) *
3908 sizeof(CommandBufferEntry); // NOLINT
3910 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
3912 if (DebugImpl && doing_gpu_trace)
3913 gpu_tracer_->End(kTraceDecoder);
3915 if (DebugImpl && debug()) {
3917 while ((error = glGetError()) != GL_NO_ERROR) {
3918 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3919 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
3920 << " : " << GetCommandName(command);
3921 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3925 result = error::kInvalidArguments;
3928 result = DoCommonCommand(command, arg_count, cmd_data);
3932 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3933 GetCommandName(command));
3936 if (result == error::kNoError &&
3937 current_decoder_error_ != error::kNoError) {
3938 result = current_decoder_error_;
3939 current_decoder_error_ = error::kNoError;
3942 if (result != error::kDeferCommandUntilLater) {
3943 process_pos += size;
3948 if (entries_processed)
3949 *entries_processed = process_pos;
3951 if (error::IsError(result)) {
3952 LOG(ERROR) << "Error: " << result << " for Command "
3953 << GetCommandName(command);
3959 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
3962 int* entries_processed) {
3963 if (gpu_debug_commands_) {
3964 return DoCommandsImpl<true>(
3965 num_commands, buffer, num_entries, entries_processed);
3967 return DoCommandsImpl<false>(
3968 num_commands, buffer, num_entries, entries_processed);
3972 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3973 buffer_manager()->RemoveBuffer(client_id);
3976 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3977 if (GetProgram(client_id)) {
3980 GLuint service_id = glCreateProgram();
3981 if (service_id != 0) {
3982 CreateProgram(client_id, service_id);
3987 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3988 if (GetShader(client_id)) {
3991 GLuint service_id = glCreateShader(type);
3992 if (service_id != 0) {
3993 CreateShader(client_id, service_id, type);
3998 void GLES2DecoderImpl::DoFinish() {
4000 ProcessPendingReadPixels();
4001 ProcessPendingQueries(true);
4004 void GLES2DecoderImpl::DoFlush() {
4006 ProcessPendingQueries(false);
4009 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4010 GLuint texture_index = texture_unit - GL_TEXTURE0;
4011 if (texture_index >= state_.texture_units.size()) {
4012 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4013 "glActiveTexture", texture_unit, "texture_unit");
4016 state_.active_texture_unit = texture_index;
4017 glActiveTexture(texture_unit);
4020 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4021 Buffer* buffer = NULL;
4022 GLuint service_id = 0;
4023 if (client_id != 0) {
4024 buffer = GetBuffer(client_id);
4026 if (!group_->bind_generates_resource()) {
4027 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4029 "id not generated by glGenBuffers");
4033 // It's a new id so make a buffer buffer for it.
4034 glGenBuffersARB(1, &service_id);
4035 CreateBuffer(client_id, service_id);
4036 buffer = GetBuffer(client_id);
4039 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4041 if (!buffer_manager()->SetTarget(buffer, target)) {
4043 GL_INVALID_OPERATION,
4044 "glBindBuffer", "buffer bound to more than 1 target");
4047 service_id = buffer->service_id();
4050 case GL_ARRAY_BUFFER:
4051 state_.bound_array_buffer = buffer;
4053 case GL_ELEMENT_ARRAY_BUFFER:
4054 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
4057 NOTREACHED(); // Validation should prevent us getting here.
4060 glBindBuffer(target, service_id);
4063 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4064 bool all_draw_buffers) {
4065 Framebuffer* framebuffer =
4066 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4067 if (!all_draw_buffers || !framebuffer) {
4068 return (GLES2Util::GetChannelsForFormat(
4069 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4071 return framebuffer->HasAlphaMRT();
4074 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4075 Framebuffer* framebuffer =
4076 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4078 return framebuffer->HasDepthAttachment();
4080 if (offscreen_target_frame_buffer_.get()) {
4081 return offscreen_target_depth_format_ != 0;
4083 return back_buffer_has_depth_;
4086 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4087 Framebuffer* framebuffer =
4088 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4090 return framebuffer->HasStencilAttachment();
4092 if (offscreen_target_frame_buffer_.get()) {
4093 return offscreen_target_stencil_format_ != 0 ||
4094 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4096 return back_buffer_has_stencil_;
4099 void GLES2DecoderImpl::ApplyDirtyState() {
4100 if (framebuffer_state_.clear_state_dirty) {
4101 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4102 state_.SetDeviceColorMask(state_.color_mask_red,
4103 state_.color_mask_green,
4104 state_.color_mask_blue,
4105 state_.color_mask_alpha && have_alpha);
4107 bool have_depth = BoundFramebufferHasDepthAttachment();
4108 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4110 bool have_stencil = BoundFramebufferHasStencilAttachment();
4111 state_.SetDeviceStencilMaskSeparate(
4112 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4113 state_.SetDeviceStencilMaskSeparate(
4114 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4116 state_.SetDeviceCapabilityState(
4117 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4118 state_.SetDeviceCapabilityState(
4119 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4120 framebuffer_state_.clear_state_dirty = false;
4124 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4125 return (offscreen_target_frame_buffer_.get())
4126 ? offscreen_target_frame_buffer_->id()
4127 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4130 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4131 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4132 "context", logger_.GetLogPrefix());
4133 // Restore the Framebuffer first because of bugs in Intel drivers.
4134 // Intel drivers incorrectly clip the viewport settings to
4135 // the size of the current framebuffer object.
4136 RestoreFramebufferBindings();
4137 state_.RestoreState(prev_state);
4140 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4142 framebuffer_state_.bound_draw_framebuffer.get()
4143 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4144 : GetBackbufferServiceId();
4145 if (!features().chromium_framebuffer_multisample) {
4146 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4148 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4149 service_id = framebuffer_state_.bound_read_framebuffer.get()
4150 ? framebuffer_state_.bound_read_framebuffer->service_id()
4151 : GetBackbufferServiceId();
4152 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4157 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4158 state_.RestoreRenderbufferBindings();
4161 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4162 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4164 GLenum target = texture->target();
4165 glBindTexture(target, service_id);
4167 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4169 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4171 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4173 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4174 RestoreTextureUnitBindings(state_.active_texture_unit);
4178 void GLES2DecoderImpl::ClearAllAttributes() const {
4179 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4181 if (feature_info_->feature_flags().native_vertex_array_object)
4182 glBindVertexArrayOES(0);
4184 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4185 if (i != 0) // Never disable attribute 0
4186 glDisableVertexAttribArray(i);
4187 if(features().angle_instanced_arrays)
4188 glVertexAttribDivisorANGLE(i, 0);
4192 void GLES2DecoderImpl::RestoreAllAttributes() const {
4193 state_.RestoreVertexAttribs();
4196 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4197 state_.SetIgnoreCachedStateForTest(ignore);
4200 void GLES2DecoderImpl::OnFboChanged() const {
4201 if (workarounds().restore_scissor_on_fbo_change)
4202 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
4205 // Called after the FBO is checked for completeness.
4206 void GLES2DecoderImpl::OnUseFramebuffer() const {
4207 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
4208 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
4209 // The driver forgets the correct scissor when modifying the FBO binding.
4210 glScissor(state_.scissor_x,
4212 state_.scissor_width,
4213 state_.scissor_height);
4215 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4216 // it's unclear how this bug works.
4221 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4222 Framebuffer* framebuffer = NULL;
4223 GLuint service_id = 0;
4224 if (client_id != 0) {
4225 framebuffer = GetFramebuffer(client_id);
4227 if (!group_->bind_generates_resource()) {
4228 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4229 "glBindFramebuffer",
4230 "id not generated by glGenFramebuffers");
4234 // It's a new id so make a framebuffer framebuffer for it.
4235 glGenFramebuffersEXT(1, &service_id);
4236 CreateFramebuffer(client_id, service_id);
4237 framebuffer = GetFramebuffer(client_id);
4239 service_id = framebuffer->service_id();
4241 framebuffer->MarkAsValid();
4243 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4245 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4246 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4249 // vmiura: This looks like dup code
4250 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4251 framebuffer_state_.bound_read_framebuffer = framebuffer;
4254 framebuffer_state_.clear_state_dirty = true;
4256 // If we are rendering to the backbuffer get the FBO id for any simulated
4258 if (framebuffer == NULL) {
4259 service_id = GetBackbufferServiceId();
4262 glBindFramebufferEXT(target, service_id);
4266 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4267 Renderbuffer* renderbuffer = NULL;
4268 GLuint service_id = 0;
4269 if (client_id != 0) {
4270 renderbuffer = GetRenderbuffer(client_id);
4271 if (!renderbuffer) {
4272 if (!group_->bind_generates_resource()) {
4273 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4274 "glBindRenderbuffer",
4275 "id not generated by glGenRenderbuffers");
4279 // It's a new id so make a renderbuffer for it.
4280 glGenRenderbuffersEXT(1, &service_id);
4281 CreateRenderbuffer(client_id, service_id);
4282 renderbuffer = GetRenderbuffer(client_id);
4284 service_id = renderbuffer->service_id();
4286 renderbuffer->MarkAsValid();
4288 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4289 state_.bound_renderbuffer = renderbuffer;
4290 state_.bound_renderbuffer_valid = true;
4291 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4294 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4295 TextureRef* texture_ref = NULL;
4296 GLuint service_id = 0;
4297 if (client_id != 0) {
4298 texture_ref = GetTexture(client_id);
4300 if (!group_->bind_generates_resource()) {
4301 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4303 "id not generated by glGenTextures");
4307 // It's a new id so make a texture texture for it.
4308 glGenTextures(1, &service_id);
4309 DCHECK_NE(0u, service_id);
4310 CreateTexture(client_id, service_id);
4311 texture_ref = GetTexture(client_id);
4314 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4317 // Check the texture exists
4319 Texture* texture = texture_ref->texture();
4320 // Check that we are not trying to bind it to a different target.
4321 if (texture->target() != 0 && texture->target() != target) {
4322 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4324 "texture bound to more than 1 target.");
4327 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4328 if (texture->target() == 0) {
4329 texture_manager()->SetTarget(texture_ref, target);
4331 glBindTexture(target, texture->service_id());
4333 glBindTexture(target, 0);
4336 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4337 unit.bind_target = target;
4340 unit.bound_texture_2d = texture_ref;
4342 case GL_TEXTURE_CUBE_MAP:
4343 unit.bound_texture_cube_map = texture_ref;
4345 case GL_TEXTURE_EXTERNAL_OES:
4346 unit.bound_texture_external_oes = texture_ref;
4348 case GL_TEXTURE_RECTANGLE_ARB:
4349 unit.bound_texture_rectangle_arb = texture_ref;
4352 NOTREACHED(); // Validation should prevent us getting here.
4357 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4358 if (state_.vertex_attrib_manager->Enable(index, false)) {
4360 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4361 glDisableVertexAttribArray(index);
4366 "glDisableVertexAttribArray", "index out of range");
4370 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4371 GLsizei numAttachments,
4372 const GLenum* attachments) {
4373 Framebuffer* framebuffer =
4374 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4376 // Validates the attachments. If one of them fails
4377 // the whole command fails.
4378 for (GLsizei i = 0; i < numAttachments; ++i) {
4380 !validators_->attachment.IsValid(attachments[i])) ||
4382 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4383 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4384 "glDiscardFramebufferEXT", attachments[i], "attachments");
4389 // Marks each one of them as not cleared
4390 for (GLsizei i = 0; i < numAttachments; ++i) {
4392 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4397 switch (attachments[i]) {
4399 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4402 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4403 case GL_STENCIL_EXT:
4404 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4413 // If the default framebuffer is bound but we are still rendering to an
4414 // FBO, translate attachment names that refer to default framebuffer
4415 // channels to corresponding framebuffer attachments.
4416 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4417 for (GLsizei i = 0; i < numAttachments; ++i) {
4418 GLenum attachment = attachments[i];
4419 if (!framebuffer && GetBackbufferServiceId()) {
4420 switch (attachment) {
4422 attachment = GL_COLOR_ATTACHMENT0;
4425 attachment = GL_DEPTH_ATTACHMENT;
4427 case GL_STENCIL_EXT:
4428 attachment = GL_STENCIL_ATTACHMENT;
4435 translated_attachments[i] = attachment;
4438 ScopedRenderTo do_render(framebuffer);
4439 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4442 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4443 if (state_.vertex_attrib_manager->Enable(index, true)) {
4444 glEnableVertexAttribArray(index);
4447 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4451 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4452 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4455 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4457 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4461 if (target == GL_TEXTURE_CUBE_MAP) {
4462 for (int i = 0; i < 6; ++i) {
4463 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4464 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4466 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4471 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4473 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4478 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4479 // Workaround for Mac driver bug. In the large scheme of things setting
4480 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4481 // hit so there's probably no need to make this conditional. The bug appears
4482 // to be that if the filtering mode is set to something that doesn't require
4483 // mipmaps for rendering, or is never set to something other than the default,
4484 // then glGenerateMipmap misbehaves.
4485 if (workarounds().set_texture_filter_before_generating_mipmap) {
4486 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4488 glGenerateMipmapEXT(target);
4489 if (workarounds().set_texture_filter_before_generating_mipmap) {
4490 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4491 texture_ref->texture()->min_filter());
4493 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4494 if (error == GL_NO_ERROR) {
4495 texture_manager()->MarkMipmapsGenerated(texture_ref);
4499 bool GLES2DecoderImpl::GetHelper(
4500 GLenum pname, GLint* params, GLsizei* num_written) {
4501 DCHECK(num_written);
4502 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4504 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4506 // Return the GL implementation's preferred format and (see below type)
4507 // if we have the GL extension that exposes this. This allows the GPU
4508 // client to use the implementation's preferred format for glReadPixels
4509 // for optimisation.
4511 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4512 // case when requested on integer/floating point buffers but which is
4513 // acceptable on GLES2 and with the GL_OES_read_format extension.
4515 // Therefore if an error occurs we swallow the error and use the
4516 // internal implementation.
4518 if (context_->HasExtension("GL_OES_read_format")) {
4519 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4521 glGetIntegerv(pname, params);
4522 if (glGetError() == GL_NO_ERROR)
4525 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4526 GetBoundReadFrameBufferInternalFormat());
4529 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4532 if (context_->HasExtension("GL_OES_read_format")) {
4533 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4535 glGetIntegerv(pname, params);
4536 if (glGetError() == GL_NO_ERROR)
4539 *params = GLES2Util::GetPreferredGLReadPixelsType(
4540 GetBoundReadFrameBufferInternalFormat(),
4541 GetBoundReadFrameBufferTextureType());
4544 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4547 *params = group_->max_fragment_uniform_vectors();
4550 case GL_MAX_VARYING_VECTORS:
4553 *params = group_->max_varying_vectors();
4556 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4559 *params = group_->max_vertex_uniform_vectors();
4565 case GL_MAX_VIEWPORT_DIMS:
4566 if (offscreen_target_frame_buffer_.get()) {
4569 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4570 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4575 case GL_MAX_SAMPLES:
4578 params[0] = renderbuffer_manager()->max_samples();
4581 case GL_MAX_RENDERBUFFER_SIZE:
4584 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4587 case GL_MAX_TEXTURE_SIZE:
4590 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4593 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4596 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4599 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4602 params[0] = group_->max_color_attachments();
4605 case GL_MAX_DRAW_BUFFERS_ARB:
4608 params[0] = group_->max_draw_buffers();
4615 glGetIntegerv(GL_ALPHA_BITS, &v);
4616 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4623 glGetIntegerv(GL_DEPTH_BITS, &v);
4624 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4627 case GL_STENCIL_BITS:
4631 glGetIntegerv(GL_STENCIL_BITS, &v);
4632 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4635 case GL_COMPRESSED_TEXTURE_FORMATS:
4636 *num_written = validators_->compressed_texture_format.GetValues().size();
4638 for (GLint ii = 0; ii < *num_written; ++ii) {
4639 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4643 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4646 *params = validators_->compressed_texture_format.GetValues().size();
4649 case GL_NUM_SHADER_BINARY_FORMATS:
4652 *params = validators_->shader_binary_format.GetValues().size();
4655 case GL_SHADER_BINARY_FORMATS:
4656 *num_written = validators_->shader_binary_format.GetValues().size();
4658 for (GLint ii = 0; ii < *num_written; ++ii) {
4659 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4663 case GL_SHADER_COMPILER:
4669 case GL_ARRAY_BUFFER_BINDING:
4672 if (state_.bound_array_buffer.get()) {
4673 GLuint client_id = 0;
4674 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4676 *params = client_id;
4682 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4685 if (state_.vertex_attrib_manager->element_array_buffer()) {
4686 GLuint client_id = 0;
4687 buffer_manager()->GetClientId(
4688 state_.vertex_attrib_manager->element_array_buffer()->
4689 service_id(), &client_id);
4690 *params = client_id;
4696 case GL_FRAMEBUFFER_BINDING:
4697 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4700 Framebuffer* framebuffer =
4701 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4703 GLuint client_id = 0;
4704 framebuffer_manager()->GetClientId(
4705 framebuffer->service_id(), &client_id);
4706 *params = client_id;
4712 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4715 Framebuffer* framebuffer =
4716 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4718 GLuint client_id = 0;
4719 framebuffer_manager()->GetClientId(
4720 framebuffer->service_id(), &client_id);
4721 *params = client_id;
4727 case GL_RENDERBUFFER_BINDING:
4730 Renderbuffer* renderbuffer =
4731 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4733 *params = renderbuffer->client_id();
4739 case GL_CURRENT_PROGRAM:
4742 if (state_.current_program.get()) {
4743 GLuint client_id = 0;
4744 program_manager()->GetClientId(
4745 state_.current_program->service_id(), &client_id);
4746 *params = client_id;
4752 case GL_VERTEX_ARRAY_BINDING_OES:
4755 if (state_.vertex_attrib_manager.get() !=
4756 state_.default_vertex_attrib_manager.get()) {
4757 GLuint client_id = 0;
4758 vertex_array_manager_->GetClientId(
4759 state_.vertex_attrib_manager->service_id(), &client_id);
4760 *params = client_id;
4766 case GL_TEXTURE_BINDING_2D:
4769 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4770 if (unit.bound_texture_2d.get()) {
4771 *params = unit.bound_texture_2d->client_id();
4777 case GL_TEXTURE_BINDING_CUBE_MAP:
4780 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4781 if (unit.bound_texture_cube_map.get()) {
4782 *params = unit.bound_texture_cube_map->client_id();
4788 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4791 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4792 if (unit.bound_texture_external_oes.get()) {
4793 *params = unit.bound_texture_external_oes->client_id();
4799 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4802 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4803 if (unit.bound_texture_rectangle_arb.get()) {
4804 *params = unit.bound_texture_rectangle_arb->client_id();
4810 case GL_UNPACK_FLIP_Y_CHROMIUM:
4813 params[0] = unpack_flip_y_;
4816 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4819 params[0] = unpack_premultiply_alpha_;
4822 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4825 params[0] = unpack_unpremultiply_alpha_;
4828 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4831 params[0] = group_->bind_generates_resource() ? 1 : 0;
4835 if (pname >= GL_DRAW_BUFFER0_ARB &&
4836 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4839 Framebuffer* framebuffer =
4840 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4842 params[0] = framebuffer->GetDrawBuffer(pname);
4843 } else { // backbuffer
4844 if (pname == GL_DRAW_BUFFER0_ARB)
4845 params[0] = group_->draw_buffer();
4847 params[0] = GL_NONE;
4852 *num_written = util_.GLGetNumValuesReturned(pname);
4857 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4858 GLenum pname, GLsizei* num_values) {
4859 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4862 return GetHelper(pname, NULL, num_values);
4865 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4866 if (GL_MAX_SAMPLES == pname &&
4867 features().use_img_for_multisampled_render_to_texture) {
4868 return GL_MAX_SAMPLES_IMG;
4873 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4875 GLsizei num_written = 0;
4876 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4877 scoped_ptr<GLint[]> values(new GLint[num_written]);
4878 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4879 GetHelper(pname, values.get(), &num_written);
4881 for (GLsizei ii = 0; ii < num_written; ++ii) {
4882 params[ii] = static_cast<GLboolean>(values[ii]);
4885 pname = AdjustGetPname(pname);
4886 glGetBooleanv(pname, params);
4890 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4892 GLsizei num_written = 0;
4893 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4894 if (GetHelper(pname, NULL, &num_written)) {
4895 scoped_ptr<GLint[]> values(new GLint[num_written]);
4896 GetHelper(pname, values.get(), &num_written);
4897 for (GLsizei ii = 0; ii < num_written; ++ii) {
4898 params[ii] = static_cast<GLfloat>(values[ii]);
4901 pname = AdjustGetPname(pname);
4902 glGetFloatv(pname, params);
4907 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4909 GLsizei num_written;
4910 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4911 !GetHelper(pname, params, &num_written)) {
4912 pname = AdjustGetPname(pname);
4913 glGetIntegerv(pname, params);
4917 void GLES2DecoderImpl::DoGetProgramiv(
4918 GLuint program_id, GLenum pname, GLint* params) {
4919 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4923 program->GetProgramiv(pname, params);
4926 void GLES2DecoderImpl::DoGetBufferParameteriv(
4927 GLenum target, GLenum pname, GLint* params) {
4928 // Just delegate it. Some validation is actually done before this.
4929 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4930 &state_, target, pname, params);
4933 void GLES2DecoderImpl::DoBindAttribLocation(
4934 GLuint program_id, GLuint index, const char* name) {
4935 if (!StringIsValidForGLES(name)) {
4937 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4940 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4942 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4945 if (index >= group_->max_vertex_attribs()) {
4947 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4950 Program* program = GetProgramInfoNotShader(
4951 program_id, "glBindAttribLocation");
4955 // At this point, the program's shaders may not be translated yet,
4956 // therefore, we may not find the hashed attribute name.
4957 // glBindAttribLocation call with original name is useless.
4958 // So instead, we should simply cache the binding, and then call
4959 // Program::ExecuteBindAttribLocationCalls() right before link.
4960 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4961 // TODO(zmo): Get rid of the following glBindAttribLocation call.
4962 glBindAttribLocation(program->service_id(), index, name);
4965 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4966 uint32 immediate_data_size,
4967 const void* cmd_data) {
4968 const gles2::cmds::BindAttribLocationBucket& c =
4969 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
4970 GLuint program = static_cast<GLuint>(c.program);
4971 GLuint index = static_cast<GLuint>(c.index);
4972 Bucket* bucket = GetBucket(c.name_bucket_id);
4973 if (!bucket || bucket->size() == 0) {
4974 return error::kInvalidArguments;
4976 std::string name_str;
4977 if (!bucket->GetAsString(&name_str)) {
4978 return error::kInvalidArguments;
4980 DoBindAttribLocation(program, index, name_str.c_str());
4981 return error::kNoError;
4984 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4985 GLuint program_id, GLint location, const char* name) {
4986 if (!StringIsValidForGLES(name)) {
4989 "glBindUniformLocationCHROMIUM", "Invalid character");
4992 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4994 GL_INVALID_OPERATION,
4995 "glBindUniformLocationCHROMIUM", "reserved prefix");
4998 if (location < 0 || static_cast<uint32>(location) >=
4999 (group_->max_fragment_uniform_vectors() +
5000 group_->max_vertex_uniform_vectors()) * 4) {
5003 "glBindUniformLocationCHROMIUM", "location out of range");
5006 Program* program = GetProgramInfoNotShader(
5007 program_id, "glBindUniformLocationCHROMIUM");
5011 if (!program->SetUniformLocationBinding(name, location)) {
5014 "glBindUniformLocationCHROMIUM", "location out of range");
5018 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5019 uint32 immediate_data_size,
5020 const void* cmd_data) {
5021 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5022 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5024 GLuint program = static_cast<GLuint>(c.program);
5025 GLint location = static_cast<GLint>(c.location);
5026 Bucket* bucket = GetBucket(c.name_bucket_id);
5027 if (!bucket || bucket->size() == 0) {
5028 return error::kInvalidArguments;
5030 std::string name_str;
5031 if (!bucket->GetAsString(&name_str)) {
5032 return error::kInvalidArguments;
5034 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5035 return error::kNoError;
5038 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5039 const void* cmd_data) {
5040 const gles2::cmds::DeleteShader& c =
5041 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5042 GLuint client_id = c.shader;
5044 Shader* shader = GetShader(client_id);
5046 if (!shader->IsDeleted()) {
5047 glDeleteShader(shader->service_id());
5048 shader_manager()->MarkAsDeleted(shader);
5051 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5054 return error::kNoError;
5057 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5058 const void* cmd_data) {
5059 const gles2::cmds::DeleteProgram& c =
5060 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5061 GLuint client_id = c.program;
5063 Program* program = GetProgram(client_id);
5065 if (!program->IsDeleted()) {
5066 program_manager()->MarkAsDeleted(shader_manager(), program);
5070 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5073 return error::kNoError;
5076 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5077 DCHECK(!ShouldDeferDraws());
5078 if (CheckBoundFramebuffersValid("glClear")) {
5080 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5083 return error::kNoError;
5086 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5087 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5088 GLuint client_renderbuffer_id) {
5089 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5092 GL_INVALID_OPERATION,
5093 "glFramebufferRenderbuffer", "no framebuffer bound");
5096 GLuint service_id = 0;
5097 Renderbuffer* renderbuffer = NULL;
5098 if (client_renderbuffer_id) {
5099 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5100 if (!renderbuffer) {
5102 GL_INVALID_OPERATION,
5103 "glFramebufferRenderbuffer", "unknown renderbuffer");
5106 service_id = renderbuffer->service_id();
5108 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5109 glFramebufferRenderbufferEXT(
5110 target, attachment, renderbuffertarget, service_id);
5111 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5112 if (error == GL_NO_ERROR) {
5113 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5115 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5116 framebuffer_state_.clear_state_dirty = true;
5121 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5122 if (SetCapabilityState(cap, false)) {
5127 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5128 if (SetCapabilityState(cap, true)) {
5133 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5134 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5135 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5136 glDepthRange(znear, zfar);
5139 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5140 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5141 state_.sample_coverage_invert = (invert != 0);
5142 glSampleCoverage(state_.sample_coverage_value, invert);
5145 // Assumes framebuffer is complete.
5146 void GLES2DecoderImpl::ClearUnclearedAttachments(
5147 GLenum target, Framebuffer* framebuffer) {
5148 if (target == GL_READ_FRAMEBUFFER_EXT) {
5149 // bind this to the DRAW point, clear then bind back to READ
5150 // TODO(gman): I don't think there is any guarantee that an FBO that
5151 // is complete on the READ attachment will be complete as a DRAW
5153 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5154 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5156 GLbitfield clear_bits = 0;
5157 if (framebuffer->HasUnclearedColorAttachments()) {
5160 (GLES2Util::GetChannelsForFormat(
5161 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5163 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5164 clear_bits |= GL_COLOR_BUFFER_BIT;
5165 if (feature_info_->feature_flags().ext_draw_buffers)
5166 framebuffer->PrepareDrawBuffersForClear();
5169 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5170 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5172 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5173 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5174 clear_bits |= GL_STENCIL_BUFFER_BIT;
5177 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5178 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5180 state_.SetDeviceDepthMask(GL_TRUE);
5181 clear_bits |= GL_DEPTH_BUFFER_BIT;
5184 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5185 glClear(clear_bits);
5187 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5188 feature_info_->feature_flags().ext_draw_buffers)
5189 framebuffer->RestoreDrawBuffersAfterClear();
5191 framebuffer_manager()->MarkAttachmentsAsCleared(
5192 framebuffer, renderbuffer_manager(), texture_manager());
5194 RestoreClearState();
5196 if (target == GL_READ_FRAMEBUFFER_EXT) {
5197 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5198 Framebuffer* draw_framebuffer =
5199 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5200 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5201 GetBackbufferServiceId();
5202 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5206 void GLES2DecoderImpl::RestoreClearState() {
5207 framebuffer_state_.clear_state_dirty = true;
5209 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5210 state_.color_clear_alpha);
5211 glClearStencil(state_.stencil_clear);
5212 glClearDepth(state_.depth_clear);
5213 if (state_.enable_flags.scissor_test) {
5214 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5218 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5219 Framebuffer* framebuffer =
5220 GetFramebufferInfoForTarget(target);
5222 return GL_FRAMEBUFFER_COMPLETE;
5224 GLenum completeness = framebuffer->IsPossiblyComplete();
5225 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5226 return completeness;
5228 return framebuffer->GetStatus(texture_manager(), target);
5231 void GLES2DecoderImpl::DoFramebufferTexture2D(
5232 GLenum target, GLenum attachment, GLenum textarget,
5233 GLuint client_texture_id, GLint level) {
5234 DoFramebufferTexture2DCommon(
5235 "glFramebufferTexture2D", target, attachment,
5236 textarget, client_texture_id, level, 0);
5239 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5240 GLenum target, GLenum attachment, GLenum textarget,
5241 GLuint client_texture_id, GLint level, GLsizei samples) {
5242 DoFramebufferTexture2DCommon(
5243 "glFramebufferTexture2DMultisample", target, attachment,
5244 textarget, client_texture_id, level, samples);
5247 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5248 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5249 GLuint client_texture_id, GLint level, GLsizei samples) {
5250 if (samples > renderbuffer_manager()->max_samples()) {
5253 "glFramebufferTexture2DMultisample", "samples too large");
5256 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5259 GL_INVALID_OPERATION,
5260 name, "no framebuffer bound.");
5263 GLuint service_id = 0;
5264 TextureRef* texture_ref = NULL;
5265 if (client_texture_id) {
5266 texture_ref = GetTexture(client_texture_id);
5269 GL_INVALID_OPERATION,
5270 name, "unknown texture_ref");
5273 service_id = texture_ref->service_id();
5276 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5279 name, "level out of range");
5284 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5286 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5288 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5290 if (features().use_img_for_multisampled_render_to_texture) {
5291 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5292 service_id, level, samples);
5294 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5295 service_id, level, samples);
5298 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5299 if (error == GL_NO_ERROR) {
5300 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5303 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5304 framebuffer_state_.clear_state_dirty = true;
5308 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5313 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5314 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5315 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5318 GL_INVALID_OPERATION,
5319 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5322 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5323 const Framebuffer::Attachment* attachment_object =
5324 framebuffer->GetAttachment(attachment);
5325 *params = attachment_object ? attachment_object->object_name() : 0;
5327 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5328 features().use_img_for_multisampled_render_to_texture) {
5329 pname = GL_TEXTURE_SAMPLES_IMG;
5331 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5335 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5336 GLenum target, GLenum pname, GLint* params) {
5337 Renderbuffer* renderbuffer =
5338 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5339 if (!renderbuffer) {
5341 GL_INVALID_OPERATION,
5342 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5346 EnsureRenderbufferBound();
5348 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5349 *params = renderbuffer->internal_format();
5351 case GL_RENDERBUFFER_WIDTH:
5352 *params = renderbuffer->width();
5354 case GL_RENDERBUFFER_HEIGHT:
5355 *params = renderbuffer->height();
5357 case GL_RENDERBUFFER_SAMPLES_EXT:
5358 if (features().use_img_for_multisampled_render_to_texture) {
5359 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5362 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5366 glGetRenderbufferParameterivEXT(target, pname, params);
5371 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5372 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5373 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5374 GLbitfield mask, GLenum filter) {
5375 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5377 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5381 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5382 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5383 BlitFramebufferHelper(
5384 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5385 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5386 state_.enable_flags.scissor_test);
5389 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5390 if (!state_.bound_renderbuffer_valid) {
5391 state_.bound_renderbuffer_valid = true;
5392 glBindRenderbufferEXT(GL_RENDERBUFFER,
5393 state_.bound_renderbuffer.get()
5394 ? state_.bound_renderbuffer->service_id()
5399 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5400 const FeatureInfo* feature_info,
5403 GLenum internal_format,
5406 // TODO(sievers): This could be resolved at the GL binding level, but the
5407 // binding process is currently a bit too 'brute force'.
5408 if (feature_info->feature_flags().is_angle) {
5409 glRenderbufferStorageMultisampleANGLE(
5410 target, samples, internal_format, width, height);
5411 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5412 glRenderbufferStorageMultisample(
5413 target, samples, internal_format, width, height);
5415 glRenderbufferStorageMultisampleEXT(
5416 target, samples, internal_format, width, height);
5420 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5430 // TODO(sievers): This could be resolved at the GL binding level, but the
5431 // binding process is currently a bit too 'brute force'.
5432 if (feature_info_->feature_flags().is_angle) {
5433 glBlitFramebufferANGLE(
5434 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5435 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5437 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5439 glBlitFramebufferEXT(
5440 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5444 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5446 GLenum internalformat,
5449 if (samples > renderbuffer_manager()->max_samples()) {
5452 "glRenderbufferStorageMultisample", "samples too large");
5456 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5457 height > renderbuffer_manager()->max_renderbuffer_size()) {
5460 "glRenderbufferStorageMultisample", "dimensions too large");
5464 uint32 estimated_size = 0;
5465 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5466 width, height, samples, internalformat, &estimated_size)) {
5469 "glRenderbufferStorageMultisample", "dimensions too large");
5473 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5476 "glRenderbufferStorageMultisample", "out of memory");
5483 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5484 GLenum target, GLsizei samples, GLenum internalformat,
5485 GLsizei width, GLsizei height) {
5486 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5487 if (!renderbuffer) {
5488 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5489 "glRenderbufferStorageMultisampleCHROMIUM",
5490 "no renderbuffer bound");
5494 if (!ValidateRenderbufferStorageMultisample(
5495 samples, internalformat, width, height)) {
5499 EnsureRenderbufferBound();
5500 GLenum impl_format =
5501 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5503 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5504 "glRenderbufferStorageMultisampleCHROMIUM");
5505 RenderbufferStorageMultisampleHelper(
5506 feature_info_.get(), target, samples, impl_format, width, height);
5508 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5509 if (error == GL_NO_ERROR) {
5511 if (workarounds().validate_multisample_buffer_allocation) {
5512 if (!VerifyMultisampleRenderbufferIntegrity(
5513 renderbuffer->service_id(), impl_format)) {
5516 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5521 // TODO(gman): If renderbuffers tracked which framebuffers they were
5522 // attached to we could just mark those framebuffers as not complete.
5523 framebuffer_manager()->IncFramebufferStateChangeCount();
5524 renderbuffer_manager()->SetInfo(
5525 renderbuffer, samples, internalformat, width, height);
5529 // This is the handler for multisampled_render_to_texture extensions.
5530 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5531 GLenum target, GLsizei samples, GLenum internalformat,
5532 GLsizei width, GLsizei height) {
5533 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5534 if (!renderbuffer) {
5535 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5536 "glRenderbufferStorageMultisampleEXT",
5537 "no renderbuffer bound");
5541 if (!ValidateRenderbufferStorageMultisample(
5542 samples, internalformat, width, height)) {
5546 EnsureRenderbufferBound();
5547 GLenum impl_format =
5548 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5550 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5551 if (features().use_img_for_multisampled_render_to_texture) {
5552 glRenderbufferStorageMultisampleIMG(
5553 target, samples, impl_format, width, height);
5555 glRenderbufferStorageMultisampleEXT(
5556 target, samples, impl_format, width, height);
5558 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5559 if (error == GL_NO_ERROR) {
5560 // TODO(gman): If renderbuffers tracked which framebuffers they were
5561 // attached to we could just mark those framebuffers as not complete.
5562 framebuffer_manager()->IncFramebufferStateChangeCount();
5563 renderbuffer_manager()->SetInfo(
5564 renderbuffer, samples, internalformat, width, height);
5568 // This function validates the allocation of a multisampled renderbuffer
5569 // by clearing it to a key color, blitting the contents to a texture, and
5570 // reading back the color to ensure it matches the key.
5571 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5572 GLuint renderbuffer, GLenum format) {
5574 // Only validate color buffers.
5575 // These formats have been selected because they are very common or are known
5576 // to be used by the WebGL backbuffer. If problems are observed with other
5577 // color formats they can be added here.
5588 GLint draw_framebuffer, read_framebuffer;
5590 // Cache framebuffer and texture bindings.
5591 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5592 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5594 if (!validation_texture_) {
5595 GLint bound_texture;
5596 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5598 // Create additional resources needed for the verification.
5599 glGenTextures(1, &validation_texture_);
5600 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5601 glGenFramebuffersEXT(1, &validation_fbo_);
5603 // Texture only needs to be 1x1.
5604 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5605 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5606 GL_UNSIGNED_BYTE, NULL);
5608 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5609 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5610 GL_TEXTURE_2D, validation_texture_, 0);
5612 glBindTexture(GL_TEXTURE_2D, bound_texture);
5615 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5616 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5617 GL_RENDERBUFFER, renderbuffer);
5619 // Cache current state and reset it to the values we require.
5620 GLboolean scissor_enabled = false;
5621 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5622 if (scissor_enabled)
5623 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5625 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5626 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5627 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5629 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5630 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5631 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5633 // Clear the buffer to the desired key color.
5634 glClear(GL_COLOR_BUFFER_BIT);
5636 // Blit from the multisample buffer to a standard texture.
5637 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5638 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5640 BlitFramebufferHelper(
5641 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5643 // Read a pixel from the buffer.
5644 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5646 unsigned char pixel[3] = {0, 0, 0};
5647 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5649 // Detach the renderbuffer.
5650 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5651 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5652 GL_RENDERBUFFER, 0);
5654 // Restore cached state.
5655 if (scissor_enabled)
5656 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5658 state_.SetDeviceColorMask(
5659 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5660 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5661 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5662 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5664 // Return true if the pixel matched the desired key color.
5665 return (pixel[0] == 0xFF &&
5670 void GLES2DecoderImpl::DoRenderbufferStorage(
5671 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5672 Renderbuffer* renderbuffer =
5673 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5674 if (!renderbuffer) {
5676 GL_INVALID_OPERATION,
5677 "glRenderbufferStorage", "no renderbuffer bound");
5681 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5682 height > renderbuffer_manager()->max_renderbuffer_size()) {
5684 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5688 uint32 estimated_size = 0;
5689 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5690 width, height, 1, internalformat, &estimated_size)) {
5692 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5696 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5698 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5702 EnsureRenderbufferBound();
5703 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5704 glRenderbufferStorageEXT(
5706 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5710 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5711 if (error == GL_NO_ERROR) {
5712 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5713 // we could just mark those framebuffers as not complete.
5714 framebuffer_manager()->IncFramebufferStateChangeCount();
5715 renderbuffer_manager()->SetInfo(
5716 renderbuffer, 1, internalformat, width, height);
5720 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5721 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5722 Program* program = GetProgramInfoNotShader(
5723 program_id, "glLinkProgram");
5728 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5729 ShaderTranslator* vertex_translator = NULL;
5730 ShaderTranslator* fragment_translator = NULL;
5731 if (use_shader_translator_) {
5732 vertex_translator = vertex_translator_.get();
5733 fragment_translator = fragment_translator_.get();
5735 if (program->Link(shader_manager(),
5737 fragment_translator,
5738 workarounds().count_all_in_varyings_packing ?
5739 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5740 shader_cache_callback_)) {
5741 if (program == state_.current_program.get()) {
5742 if (workarounds().use_current_program_after_successful_link)
5743 glUseProgram(program->service_id());
5744 if (workarounds().clear_uniforms_before_first_program_use)
5745 program_manager()->ClearUniforms(program);
5749 // LinkProgram can be very slow. Exit command processing to allow for
5750 // context preemption and GPU watchdog checks.
5751 ExitCommandProcessingEarly();
5754 void GLES2DecoderImpl::DoTexParameterf(
5755 GLenum target, GLenum pname, GLfloat param) {
5756 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5759 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5763 texture_manager()->SetParameterf(
5764 "glTexParameterf", GetErrorState(), texture, pname, param);
5767 void GLES2DecoderImpl::DoTexParameteri(
5768 GLenum target, GLenum pname, GLint param) {
5769 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5772 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5776 texture_manager()->SetParameteri(
5777 "glTexParameteri", GetErrorState(), texture, pname, param);
5780 void GLES2DecoderImpl::DoTexParameterfv(
5781 GLenum target, GLenum pname, const GLfloat* params) {
5782 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5785 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5789 texture_manager()->SetParameterf(
5790 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5793 void GLES2DecoderImpl::DoTexParameteriv(
5794 GLenum target, GLenum pname, const GLint* params) {
5795 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5799 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5803 texture_manager()->SetParameteri(
5804 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5807 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
5808 if (!state_.bound_valuebuffer.get()) {
5809 // There is no valuebuffer bound
5810 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5811 "no valuebuffer in use");
5817 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
5818 GLenum subscription,
5819 const char* function_name) {
5820 if (!CheckCurrentValuebuffer(function_name)) {
5823 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
5824 // The valuebuffer is not subscribed to the target
5825 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5826 "valuebuffer is not subscribed");
5832 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
5833 GLenum subscription,
5834 const char* function_name) {
5835 if (!CheckCurrentProgramForUniform(location, function_name)) {
5838 GLint real_location = -1;
5839 GLint array_index = -1;
5840 const Program::UniformInfo* info =
5841 state_.current_program->GetUniformInfoByFakeLocation(
5842 location, &real_location, &array_index);
5844 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
5847 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
5848 info->accepts_api_type) == 0) {
5849 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5850 "wrong type for subscription");
5856 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5857 if (!state_.current_program.get()) {
5858 // The program does not exist.
5860 GL_INVALID_OPERATION, function_name, "no program in use");
5863 if (!state_.current_program->InUse()) {
5865 GL_INVALID_OPERATION, function_name, "program not linked");
5871 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5872 GLint location, const char* function_name) {
5873 if (!CheckCurrentProgram(function_name)) {
5876 return location != -1;
5879 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
5880 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5883 const Framebuffer::Attachment* attachment =
5884 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
5888 DCHECK(state_.current_program.get());
5889 const Program::SamplerIndices& sampler_indices =
5890 state_.current_program->sampler_indices();
5891 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5892 const Program::UniformInfo* uniform_info =
5893 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5894 DCHECK(uniform_info);
5895 if (uniform_info->type != GL_SAMPLER_2D)
5897 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5898 GLuint texture_unit_index = uniform_info->texture_units[jj];
5899 if (texture_unit_index >= state_.texture_units.size())
5901 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5902 TextureRef* texture_ref =
5903 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
5904 if (attachment->IsTexture(texture_ref))
5911 bool GLES2DecoderImpl::CheckUniformForApiType(
5912 const Program::UniformInfo* info,
5913 const char* function_name,
5914 Program::UniformApiType api_type) {
5916 if ((api_type & info->accepts_api_type) == 0) {
5917 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5918 "wrong uniform function for type");
5924 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5925 GLint fake_location,
5926 const char* function_name,
5927 Program::UniformApiType api_type,
5928 GLint* real_location,
5933 DCHECK(real_location);
5935 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5938 GLint array_index = -1;
5939 const Program::UniformInfo* info =
5940 state_.current_program->GetUniformInfoByFakeLocation(
5941 fake_location, real_location, &array_index);
5944 GL_INVALID_OPERATION, function_name, "unknown location");
5947 if (!CheckUniformForApiType(info, function_name, api_type)) {
5950 if (*count > 1 && !info->is_array) {
5952 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5955 *count = std::min(info->size - array_index, *count);
5963 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5966 GLint real_location = -1;
5967 if (!PrepForSetUniformByLocation(fake_location,
5969 Program::kUniform1i,
5975 if (!state_.current_program->SetSamplers(
5976 state_.texture_units.size(), fake_location, 1, &v0)) {
5978 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5981 glUniform1i(real_location, v0);
5984 void GLES2DecoderImpl::DoUniform1iv(
5985 GLint fake_location, GLsizei count, const GLint *value) {
5987 GLint real_location = -1;
5988 if (!PrepForSetUniformByLocation(fake_location,
5990 Program::kUniform1i,
5996 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5997 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5998 if (!state_.current_program->SetSamplers(
5999 state_.texture_units.size(), fake_location, count, value)) {
6001 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6005 glUniform1iv(real_location, count, value);
6008 void GLES2DecoderImpl::DoUniform1fv(
6009 GLint fake_location, GLsizei count, const GLfloat* value) {
6011 GLint real_location = -1;
6012 if (!PrepForSetUniformByLocation(fake_location,
6014 Program::kUniform1f,
6020 if (type == GL_BOOL) {
6021 scoped_ptr<GLint[]> temp(new GLint[count]);
6022 for (GLsizei ii = 0; ii < count; ++ii) {
6023 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6025 DoUniform1iv(real_location, count, temp.get());
6027 glUniform1fv(real_location, count, value);
6031 void GLES2DecoderImpl::DoUniform2fv(
6032 GLint fake_location, GLsizei count, const GLfloat* value) {
6034 GLint real_location = -1;
6035 if (!PrepForSetUniformByLocation(fake_location,
6037 Program::kUniform2f,
6043 if (type == GL_BOOL_VEC2) {
6044 GLsizei num_values = count * 2;
6045 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6046 for (GLsizei ii = 0; ii < num_values; ++ii) {
6047 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6049 glUniform2iv(real_location, count, temp.get());
6051 glUniform2fv(real_location, count, value);
6055 void GLES2DecoderImpl::DoUniform3fv(
6056 GLint fake_location, GLsizei count, const GLfloat* value) {
6058 GLint real_location = -1;
6059 if (!PrepForSetUniformByLocation(fake_location,
6061 Program::kUniform3f,
6067 if (type == GL_BOOL_VEC3) {
6068 GLsizei num_values = count * 3;
6069 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6070 for (GLsizei ii = 0; ii < num_values; ++ii) {
6071 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6073 glUniform3iv(real_location, count, temp.get());
6075 glUniform3fv(real_location, count, value);
6079 void GLES2DecoderImpl::DoUniform4fv(
6080 GLint fake_location, GLsizei count, const GLfloat* value) {
6082 GLint real_location = -1;
6083 if (!PrepForSetUniformByLocation(fake_location,
6085 Program::kUniform4f,
6091 if (type == GL_BOOL_VEC4) {
6092 GLsizei num_values = count * 4;
6093 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6094 for (GLsizei ii = 0; ii < num_values; ++ii) {
6095 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6097 glUniform4iv(real_location, count, temp.get());
6099 glUniform4fv(real_location, count, value);
6103 void GLES2DecoderImpl::DoUniform2iv(
6104 GLint fake_location, GLsizei count, const GLint* value) {
6106 GLint real_location = -1;
6107 if (!PrepForSetUniformByLocation(fake_location,
6109 Program::kUniform2i,
6115 glUniform2iv(real_location, count, value);
6118 void GLES2DecoderImpl::DoUniform3iv(
6119 GLint fake_location, GLsizei count, const GLint* value) {
6121 GLint real_location = -1;
6122 if (!PrepForSetUniformByLocation(fake_location,
6124 Program::kUniform3i,
6130 glUniform3iv(real_location, count, value);
6133 void GLES2DecoderImpl::DoUniform4iv(
6134 GLint fake_location, GLsizei count, const GLint* value) {
6136 GLint real_location = -1;
6137 if (!PrepForSetUniformByLocation(fake_location,
6139 Program::kUniform4i,
6145 glUniform4iv(real_location, count, value);
6148 void GLES2DecoderImpl::DoUniformMatrix2fv(
6149 GLint fake_location, GLsizei count, GLboolean transpose,
6150 const GLfloat* value) {
6152 GLint real_location = -1;
6153 if (!PrepForSetUniformByLocation(fake_location,
6154 "glUniformMatrix2fv",
6155 Program::kUniformMatrix2f,
6161 glUniformMatrix2fv(real_location, count, transpose, value);
6164 void GLES2DecoderImpl::DoUniformMatrix3fv(
6165 GLint fake_location, GLsizei count, GLboolean transpose,
6166 const GLfloat* value) {
6168 GLint real_location = -1;
6169 if (!PrepForSetUniformByLocation(fake_location,
6170 "glUniformMatrix3fv",
6171 Program::kUniformMatrix3f,
6177 glUniformMatrix3fv(real_location, count, transpose, value);
6180 void GLES2DecoderImpl::DoUniformMatrix4fv(
6181 GLint fake_location, GLsizei count, GLboolean transpose,
6182 const GLfloat* value) {
6184 GLint real_location = -1;
6185 if (!PrepForSetUniformByLocation(fake_location,
6186 "glUniformMatrix4fv",
6187 Program::kUniformMatrix4f,
6193 glUniformMatrix4fv(real_location, count, transpose, value);
6196 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6197 GLuint service_id = 0;
6198 Program* program = NULL;
6200 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6204 if (!program->IsValid()) {
6205 // Program was not linked successfully. (ie, glLinkProgram)
6207 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6210 service_id = program->service_id();
6212 if (state_.current_program.get()) {
6213 program_manager()->UnuseProgram(shader_manager(),
6214 state_.current_program.get());
6216 state_.current_program = program;
6217 LogClientServiceMapping("glUseProgram", program_id, service_id);
6218 glUseProgram(service_id);
6219 if (state_.current_program.get()) {
6220 program_manager()->UseProgram(state_.current_program.get());
6221 if (workarounds().clear_uniforms_before_first_program_use)
6222 program_manager()->ClearUniforms(program);
6226 void GLES2DecoderImpl::RenderWarning(
6227 const char* filename, int line, const std::string& msg) {
6228 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6231 void GLES2DecoderImpl::PerformanceWarning(
6232 const char* filename, int line, const std::string& msg) {
6233 logger_.LogMessage(filename, line,
6234 std::string("PERFORMANCE WARNING: ") + msg);
6237 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6238 Texture* texture, GLenum textarget) {
6239 // Image is already in use if texture is attached to a framebuffer.
6240 if (texture && !texture->IsAttachedToFramebuffer()) {
6241 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6243 ScopedGLErrorSuppressor suppressor(
6244 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6246 glBindTexture(textarget, texture->service_id());
6247 image->WillUseTexImage();
6248 RestoreCurrentTextureBindings(&state_, textarget);
6253 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6254 Texture* texture, GLenum textarget) {
6255 // Image is still in use if texture is attached to a framebuffer.
6256 if (texture && !texture->IsAttachedToFramebuffer()) {
6257 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6259 ScopedGLErrorSuppressor suppressor(
6260 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6262 glBindTexture(textarget, texture->service_id());
6263 image->DidUseTexImage();
6264 RestoreCurrentTextureBindings(&state_, textarget);
6269 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6270 DCHECK(state_.current_program.get());
6271 if (!texture_manager()->HaveUnrenderableTextures() &&
6272 !texture_manager()->HaveImages()) {
6276 bool textures_set = false;
6277 const Program::SamplerIndices& sampler_indices =
6278 state_.current_program->sampler_indices();
6279 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6280 const Program::UniformInfo* uniform_info =
6281 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6282 DCHECK(uniform_info);
6283 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6284 GLuint texture_unit_index = uniform_info->texture_units[jj];
6285 if (texture_unit_index < state_.texture_units.size()) {
6286 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6287 TextureRef* texture_ref =
6288 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6289 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6290 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6291 textures_set = true;
6292 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6295 texture_manager()->black_texture_id(uniform_info->type));
6296 LOCAL_RENDER_WARNING(
6297 std::string("texture bound to texture unit ") +
6298 base::IntToString(texture_unit_index) +
6299 " is not renderable. It maybe non-power-of-2 and have"
6300 " incompatible texture filtering or is not"
6301 " 'texture complete'");
6305 if (textarget != GL_TEXTURE_CUBE_MAP) {
6306 Texture* texture = texture_ref->texture();
6307 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6308 if (image && !texture->IsAttachedToFramebuffer()) {
6309 ScopedGLErrorSuppressor suppressor(
6310 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6311 textures_set = true;
6312 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6313 image->WillUseTexImage();
6318 // else: should this be an error?
6321 return !textures_set;
6324 void GLES2DecoderImpl::RestoreStateForTextures() {
6325 DCHECK(state_.current_program.get());
6326 const Program::SamplerIndices& sampler_indices =
6327 state_.current_program->sampler_indices();
6328 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6329 const Program::UniformInfo* uniform_info =
6330 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6331 DCHECK(uniform_info);
6332 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6333 GLuint texture_unit_index = uniform_info->texture_units[jj];
6334 if (texture_unit_index < state_.texture_units.size()) {
6335 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6336 TextureRef* texture_ref =
6337 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6338 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6339 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6340 // Get the texture_ref info that was previously bound here.
6341 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6342 ? texture_unit.bound_texture_2d.get()
6343 : texture_unit.bound_texture_cube_map.get();
6344 glBindTexture(texture_unit.bind_target,
6345 texture_ref ? texture_ref->service_id() : 0);
6349 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6350 Texture* texture = texture_ref->texture();
6351 gfx::GLImage* image =
6352 texture->GetLevelImage(texture_unit.bind_target, 0);
6353 if (image && !texture->IsAttachedToFramebuffer()) {
6354 ScopedGLErrorSuppressor suppressor(
6355 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6356 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6357 image->DidUseTexImage();
6364 // Set the active texture back to whatever the user had it as.
6365 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6368 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6369 // Only check if there are some uncleared textures.
6370 if (!texture_manager()->HaveUnsafeTextures()) {
6374 // 1: Check all textures we are about to render with.
6375 if (state_.current_program.get()) {
6376 const Program::SamplerIndices& sampler_indices =
6377 state_.current_program->sampler_indices();
6378 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6379 const Program::UniformInfo* uniform_info =
6380 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6381 DCHECK(uniform_info);
6382 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6383 GLuint texture_unit_index = uniform_info->texture_units[jj];
6384 if (texture_unit_index < state_.texture_units.size()) {
6385 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6386 TextureRef* texture_ref =
6387 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6388 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6389 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6400 bool GLES2DecoderImpl::IsDrawValid(
6401 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6402 GLsizei primcount) {
6403 DCHECK(instanced || primcount == 1);
6405 // NOTE: We specifically do not check current_program->IsValid() because
6406 // it could never be invalid since glUseProgram would have failed. While
6407 // glLinkProgram could later mark the program as invalid the previous
6408 // valid program will still function if it is still the current program.
6409 if (!state_.current_program.get()) {
6410 // The program does not exist.
6411 // But GL says no ERROR.
6412 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6416 if (CheckDrawingFeedbackLoops()) {
6418 GL_INVALID_OPERATION, function_name,
6419 "Source and destination textures of the draw are the same.");
6423 return state_.vertex_attrib_manager
6424 ->ValidateBindings(function_name,
6426 feature_info_.get(),
6427 state_.current_program.get(),
6428 max_vertex_accessed,
6433 bool GLES2DecoderImpl::SimulateAttrib0(
6434 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6438 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6441 const VertexAttrib* attrib =
6442 state_.vertex_attrib_manager->GetVertexAttrib(0);
6443 // If it's enabled or it's not used then we don't need to do anything.
6444 bool attrib_0_used =
6445 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6446 if (attrib->enabled() && attrib_0_used) {
6450 // Make a buffer with a single repeated vec4 value enough to
6451 // simulate the constant value that is supposed to be here.
6452 // This is required to emulate GLES2 on GL.
6453 GLuint num_vertices = max_vertex_accessed + 1;
6454 uint32 size_needed = 0;
6456 if (num_vertices == 0 ||
6457 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6458 size_needed > 0x7FFFFFFFU) {
6459 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6463 LOCAL_PERFORMANCE_WARNING(
6464 "Attribute 0 is disabled. This has signficant performance penalty");
6466 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6467 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6469 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6471 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6472 GLenum error = glGetError();
6473 if (error != GL_NO_ERROR) {
6475 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6480 const Vec4& value = state_.attrib_values[0];
6483 (!attrib_0_buffer_matches_value_ ||
6484 (value.v[0] != attrib_0_value_.v[0] ||
6485 value.v[1] != attrib_0_value_.v[1] ||
6486 value.v[2] != attrib_0_value_.v[2] ||
6487 value.v[3] != attrib_0_value_.v[3])))) {
6488 std::vector<Vec4> temp(num_vertices, value);
6489 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6490 attrib_0_buffer_matches_value_ = true;
6491 attrib_0_value_ = value;
6492 attrib_0_size_ = size_needed;
6495 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6497 if (attrib->divisor())
6498 glVertexAttribDivisorANGLE(0, 0);
6504 void GLES2DecoderImpl::RestoreStateForAttrib(
6505 GLuint attrib_index, bool restore_array_binding) {
6506 const VertexAttrib* attrib =
6507 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6508 if (restore_array_binding) {
6509 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6510 Buffer* buffer = attrib->buffer();
6511 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6512 glVertexAttribPointer(
6513 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6514 attrib->gl_stride(), ptr);
6516 if (attrib->divisor())
6517 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6519 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6520 state_.bound_array_buffer->service_id() : 0);
6522 // Never touch vertex attribute 0's state (in particular, never
6523 // disable it) when running on desktop GL because it will never be
6525 if (attrib_index != 0 ||
6526 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6527 if (attrib->enabled()) {
6528 glEnableVertexAttribArray(attrib_index);
6530 glDisableVertexAttribArray(attrib_index);
6535 bool GLES2DecoderImpl::SimulateFixedAttribs(
6536 const char* function_name,
6537 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6540 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6543 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6547 LOCAL_PERFORMANCE_WARNING(
6548 "GL_FIXED attributes have a signficant performance penalty");
6550 // NOTE: we could be smart and try to check if a buffer is used
6551 // twice in 2 different attribs, find the overlapping parts and therefore
6552 // duplicate the minimum amount of data but this whole code path is not meant
6553 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6554 // tests so we just add to the buffer attrib used.
6556 GLuint elements_needed = 0;
6557 const VertexAttribManager::VertexAttribList& enabled_attribs =
6558 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6559 for (VertexAttribManager::VertexAttribList::const_iterator it =
6560 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6561 const VertexAttrib* attrib = *it;
6562 const Program::VertexAttrib* attrib_info =
6563 state_.current_program->GetAttribInfoByLocation(attrib->index());
6564 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6565 max_vertex_accessed);
6566 GLuint num_vertices = max_accessed + 1;
6567 if (num_vertices == 0) {
6569 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6573 attrib->CanAccess(max_accessed) &&
6574 attrib->type() == GL_FIXED) {
6575 uint32 elements_used = 0;
6576 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6577 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6579 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6585 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6586 uint32 size_needed = 0;
6587 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6588 size_needed > 0x7FFFFFFFU) {
6590 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6594 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6596 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6597 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6598 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6599 GLenum error = glGetError();
6600 if (error != GL_NO_ERROR) {
6602 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6607 // Copy the elements and convert to float
6608 GLintptr offset = 0;
6609 for (VertexAttribManager::VertexAttribList::const_iterator it =
6610 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6611 const VertexAttrib* attrib = *it;
6612 const Program::VertexAttrib* attrib_info =
6613 state_.current_program->GetAttribInfoByLocation(attrib->index());
6614 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6615 max_vertex_accessed);
6616 GLuint num_vertices = max_accessed + 1;
6617 if (num_vertices == 0) {
6619 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6623 attrib->CanAccess(max_accessed) &&
6624 attrib->type() == GL_FIXED) {
6625 int num_elements = attrib->size() * num_vertices;
6626 const int src_size = num_elements * sizeof(int32);
6627 const int dst_size = num_elements * sizeof(float);
6628 scoped_ptr<float[]> data(new float[num_elements]);
6629 const int32* src = reinterpret_cast<const int32 *>(
6630 attrib->buffer()->GetRange(attrib->offset(), src_size));
6631 const int32* end = src + num_elements;
6632 float* dst = data.get();
6633 while (src != end) {
6634 *dst++ = static_cast<float>(*src++) / 65536.0f;
6636 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
6637 glVertexAttribPointer(
6638 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6639 reinterpret_cast<GLvoid*>(offset));
6647 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6648 // There's no need to call glVertexAttribPointer because we shadow all the
6649 // settings and passing GL_FIXED to it will not work.
6652 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6656 error::Error GLES2DecoderImpl::DoDrawArrays(
6657 const char* function_name,
6662 GLsizei primcount) {
6663 error::Error error = WillAccessBoundFramebufferForDraw();
6664 if (error != error::kNoError)
6666 if (!validators_->draw_mode.IsValid(mode)) {
6667 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6668 return error::kNoError;
6671 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6672 return error::kNoError;
6674 if (primcount < 0) {
6675 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6676 return error::kNoError;
6678 if (!CheckBoundFramebuffersValid(function_name)) {
6679 return error::kNoError;
6681 // We have to check this here because the prototype for glDrawArrays
6682 // is GLint not GLsizei.
6684 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6685 return error::kNoError;
6688 if (count == 0 || primcount == 0) {
6689 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6690 return error::kNoError;
6693 GLuint max_vertex_accessed = first + count - 1;
6694 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6695 if (!ClearUnclearedTextures()) {
6696 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6697 return error::kNoError;
6699 bool simulated_attrib_0 = false;
6700 if (!SimulateAttrib0(
6701 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6702 return error::kNoError;
6704 bool simulated_fixed_attribs = false;
6705 if (SimulateFixedAttribs(
6706 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6708 bool textures_set = !PrepareTexturesForRender();
6710 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6712 glDrawArrays(mode, first, count);
6714 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6717 RestoreStateForTextures();
6719 if (simulated_fixed_attribs) {
6720 RestoreStateForSimulatedFixedAttribs();
6723 if (simulated_attrib_0) {
6724 // We don't have to restore attrib 0 generic data at the end of this
6725 // function even if it is simulated. This is because we will simulate
6726 // it in each draw call, and attrib 0 generic data queries use cached
6727 // values instead of passing down to the underlying driver.
6728 RestoreStateForAttrib(0, false);
6731 return error::kNoError;
6734 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
6735 const void* cmd_data) {
6736 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
6737 return DoDrawArrays("glDrawArrays",
6739 static_cast<GLenum>(c.mode),
6740 static_cast<GLint>(c.first),
6741 static_cast<GLsizei>(c.count),
6745 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6746 uint32 immediate_data_size,
6747 const void* cmd_data) {
6748 const gles2::cmds::DrawArraysInstancedANGLE& c =
6749 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
6750 if (!features().angle_instanced_arrays) {
6752 GL_INVALID_OPERATION,
6753 "glDrawArraysInstancedANGLE", "function not available");
6754 return error::kNoError;
6756 return DoDrawArrays("glDrawArraysIntancedANGLE",
6758 static_cast<GLenum>(c.mode),
6759 static_cast<GLint>(c.first),
6760 static_cast<GLsizei>(c.count),
6761 static_cast<GLsizei>(c.primcount));
6764 error::Error GLES2DecoderImpl::DoDrawElements(
6765 const char* function_name,
6771 GLsizei primcount) {
6772 error::Error error = WillAccessBoundFramebufferForDraw();
6773 if (error != error::kNoError)
6775 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6777 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6778 return error::kNoError;
6782 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6783 return error::kNoError;
6786 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6787 return error::kNoError;
6789 if (!validators_->draw_mode.IsValid(mode)) {
6790 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6791 return error::kNoError;
6793 if (!validators_->index_type.IsValid(type)) {
6794 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6795 return error::kNoError;
6797 if (primcount < 0) {
6798 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6799 return error::kNoError;
6802 if (!CheckBoundFramebuffersValid(function_name)) {
6803 return error::kNoError;
6806 if (count == 0 || primcount == 0) {
6807 return error::kNoError;
6810 GLuint max_vertex_accessed;
6811 Buffer* element_array_buffer =
6812 state_.vertex_attrib_manager->element_array_buffer();
6814 if (!element_array_buffer->GetMaxValueForRange(
6815 offset, count, type, &max_vertex_accessed)) {
6817 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6818 return error::kNoError;
6821 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6822 if (!ClearUnclearedTextures()) {
6823 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6824 return error::kNoError;
6826 bool simulated_attrib_0 = false;
6827 if (!SimulateAttrib0(
6828 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6829 return error::kNoError;
6831 bool simulated_fixed_attribs = false;
6832 if (SimulateFixedAttribs(
6833 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6835 bool textures_set = !PrepareTexturesForRender();
6837 // TODO(gman): Refactor to hide these details in BufferManager or
6838 // VertexAttribManager.
6839 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6840 bool used_client_side_array = false;
6841 if (element_array_buffer->IsClientSideArray()) {
6842 used_client_side_array = true;
6843 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6844 indices = element_array_buffer->GetRange(offset, 0);
6847 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6849 glDrawElements(mode, count, type, indices);
6851 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6854 if (used_client_side_array) {
6855 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6856 element_array_buffer->service_id());
6860 RestoreStateForTextures();
6862 if (simulated_fixed_attribs) {
6863 RestoreStateForSimulatedFixedAttribs();
6866 if (simulated_attrib_0) {
6867 // We don't have to restore attrib 0 generic data at the end of this
6868 // function even if it is simulated. This is because we will simulate
6869 // it in each draw call, and attrib 0 generic data queries use cached
6870 // values instead of passing down to the underlying driver.
6871 RestoreStateForAttrib(0, false);
6874 return error::kNoError;
6877 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
6878 const void* cmd_data) {
6879 const gles2::cmds::DrawElements& c =
6880 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
6881 return DoDrawElements("glDrawElements",
6883 static_cast<GLenum>(c.mode),
6884 static_cast<GLsizei>(c.count),
6885 static_cast<GLenum>(c.type),
6886 static_cast<int32>(c.index_offset),
6890 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6891 uint32 immediate_data_size,
6892 const void* cmd_data) {
6893 const gles2::cmds::DrawElementsInstancedANGLE& c =
6894 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
6895 if (!features().angle_instanced_arrays) {
6897 GL_INVALID_OPERATION,
6898 "glDrawElementsInstancedANGLE", "function not available");
6899 return error::kNoError;
6901 return DoDrawElements("glDrawElementsInstancedANGLE",
6903 static_cast<GLenum>(c.mode),
6904 static_cast<GLsizei>(c.count),
6905 static_cast<GLenum>(c.type),
6906 static_cast<int32>(c.index_offset),
6907 static_cast<GLsizei>(c.primcount));
6910 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6911 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6912 GLuint max_vertex_accessed = 0;
6913 Buffer* buffer = GetBuffer(buffer_id);
6915 // TODO(gman): Should this be a GL error or a command buffer error?
6917 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6919 if (!buffer->GetMaxValueForRange(
6920 offset, count, type, &max_vertex_accessed)) {
6921 // TODO(gman): Should this be a GL error or a command buffer error?
6923 GL_INVALID_OPERATION,
6924 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6927 return max_vertex_accessed;
6930 // Calls glShaderSource for the various versions of the ShaderSource command.
6931 // Assumes that data / data_size points to a piece of memory that is in range
6932 // of whatever context it came from (shared memory, immediate memory, bucket
6934 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6935 GLuint client_id, const char* data, uint32 data_size) {
6936 std::string str(data, data + data_size);
6937 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6939 return error::kNoError;
6941 // Note: We don't actually call glShaderSource here. We wait until
6942 // the call to glCompileShader.
6943 shader->set_source(str);
6944 return error::kNoError;
6947 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6948 uint32 immediate_data_size,
6949 const void* cmd_data) {
6950 const gles2::cmds::ShaderSourceBucket& c =
6951 *static_cast<const gles2::cmds::ShaderSourceBucket*>(cmd_data);
6952 Bucket* bucket = GetBucket(c.data_bucket_id);
6953 if (!bucket || bucket->size() == 0) {
6954 return error::kInvalidArguments;
6956 return ShaderSourceHelper(
6957 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6958 bucket->size() - 1);
6961 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6962 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6963 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6967 ShaderTranslator* translator = NULL;
6968 if (use_shader_translator_) {
6969 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6970 vertex_translator_.get() : fragment_translator_.get();
6975 feature_info_->feature_flags().angle_translated_shader_source ?
6976 Shader::kANGLE : Shader::kGL);
6978 // CompileShader can be very slow. Exit command processing to allow for
6979 // context preemption and GPU watchdog checks.
6980 ExitCommandProcessingEarly();
6983 void GLES2DecoderImpl::DoGetShaderiv(
6984 GLuint shader_id, GLenum pname, GLint* params) {
6985 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6990 case GL_SHADER_SOURCE_LENGTH:
6991 *params = shader->source().size();
6995 case GL_COMPILE_STATUS:
6996 *params = compile_shader_always_succeeds_ ? true : shader->valid();
6998 case GL_INFO_LOG_LENGTH:
6999 *params = shader->log_info().size();
7003 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7004 *params = shader->translated_source().size();
7011 glGetShaderiv(shader->service_id(), pname, params);
7014 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7015 const void* cmd_data) {
7016 const gles2::cmds::GetShaderSource& c =
7017 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7018 GLuint shader_id = c.shader;
7019 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7020 Bucket* bucket = CreateBucket(bucket_id);
7021 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7022 if (!shader || shader->source().empty()) {
7024 return error::kNoError;
7026 bucket->SetFromString(shader->source().c_str());
7027 return error::kNoError;
7030 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7031 uint32 immediate_data_size,
7032 const void* cmd_data) {
7033 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7034 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7036 GLuint shader_id = c.shader;
7037 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7038 Bucket* bucket = CreateBucket(bucket_id);
7039 Shader* shader = GetShaderInfoNotProgram(
7040 shader_id, "glGetTranslatedShaderSourceANGLE");
7043 return error::kNoError;
7046 bucket->SetFromString(shader->translated_source().c_str());
7047 return error::kNoError;
7050 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7051 uint32 immediate_data_size,
7052 const void* cmd_data) {
7053 const gles2::cmds::GetProgramInfoLog& c =
7054 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7055 GLuint program_id = c.program;
7056 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7057 Bucket* bucket = CreateBucket(bucket_id);
7058 Program* program = GetProgramInfoNotShader(
7059 program_id, "glGetProgramInfoLog");
7060 if (!program || !program->log_info()) {
7061 bucket->SetFromString("");
7062 return error::kNoError;
7064 bucket->SetFromString(program->log_info()->c_str());
7065 return error::kNoError;
7068 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7069 uint32 immediate_data_size,
7070 const void* cmd_data) {
7071 const gles2::cmds::GetShaderInfoLog& c =
7072 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7073 GLuint shader_id = c.shader;
7074 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7075 Bucket* bucket = CreateBucket(bucket_id);
7076 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7078 bucket->SetFromString("");
7079 return error::kNoError;
7081 bucket->SetFromString(shader->log_info().c_str());
7082 return error::kNoError;
7085 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7086 return state_.GetEnabled(cap);
7089 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7090 const Buffer* buffer = GetBuffer(client_id);
7091 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7094 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7095 const Framebuffer* framebuffer =
7096 GetFramebuffer(client_id);
7097 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7100 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7101 // IsProgram is true for programs as soon as they are created, until they are
7102 // deleted and no longer in use.
7103 const Program* program = GetProgram(client_id);
7104 return program != NULL && !program->IsDeleted();
7107 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7108 const Renderbuffer* renderbuffer =
7109 GetRenderbuffer(client_id);
7110 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7113 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7114 // IsShader is true for shaders as soon as they are created, until they
7115 // are deleted and not attached to any programs.
7116 const Shader* shader = GetShader(client_id);
7117 return shader != NULL && !shader->IsDeleted();
7120 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7121 const TextureRef* texture_ref = GetTexture(client_id);
7122 return texture_ref && texture_ref->texture()->IsValid();
7125 void GLES2DecoderImpl::DoAttachShader(
7126 GLuint program_client_id, GLint shader_client_id) {
7127 Program* program = GetProgramInfoNotShader(
7128 program_client_id, "glAttachShader");
7132 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7136 if (!program->AttachShader(shader_manager(), shader)) {
7138 GL_INVALID_OPERATION,
7140 "can not attach more than one shader of the same type.");
7143 glAttachShader(program->service_id(), shader->service_id());
7146 void GLES2DecoderImpl::DoDetachShader(
7147 GLuint program_client_id, GLint shader_client_id) {
7148 Program* program = GetProgramInfoNotShader(
7149 program_client_id, "glDetachShader");
7153 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7157 if (!program->DetachShader(shader_manager(), shader)) {
7159 GL_INVALID_OPERATION,
7160 "glDetachShader", "shader not attached to program");
7163 glDetachShader(program->service_id(), shader->service_id());
7166 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7167 Program* program = GetProgramInfoNotShader(
7168 program_client_id, "glValidateProgram");
7172 program->Validate();
7175 void GLES2DecoderImpl::GetVertexAttribHelper(
7176 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7178 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
7179 Buffer* buffer = attrib->buffer();
7180 if (buffer && !buffer->IsDeleted()) {
7182 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7183 *params = client_id;
7187 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7188 *params = attrib->enabled();
7190 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7191 *params = attrib->size();
7193 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7194 *params = attrib->gl_stride();
7196 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7197 *params = attrib->type();
7199 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7200 *params = attrib->normalized();
7202 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7203 *params = attrib->divisor();
7211 void GLES2DecoderImpl::DoGetTexParameterfv(
7212 GLenum target, GLenum pname, GLfloat* params) {
7213 InitTextureMaxAnisotropyIfNeeded(target, pname);
7214 glGetTexParameterfv(target, pname, params);
7217 void GLES2DecoderImpl::DoGetTexParameteriv(
7218 GLenum target, GLenum pname, GLint* params) {
7219 InitTextureMaxAnisotropyIfNeeded(target, pname);
7220 glGetTexParameteriv(target, pname, params);
7223 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7224 GLenum target, GLenum pname) {
7225 if (!workarounds().init_texture_max_anisotropy)
7227 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7228 !validators_->texture_parameter.IsValid(pname)) {
7232 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7236 GL_INVALID_OPERATION,
7237 "glGetTexParamter{fi}v", "unknown texture for target");
7240 Texture* texture = texture_ref->texture();
7241 texture->InitTextureMaxAnisotropyIfNeeded(target);
7244 void GLES2DecoderImpl::DoGetVertexAttribfv(
7245 GLuint index, GLenum pname, GLfloat* params) {
7246 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7249 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7253 case GL_CURRENT_VERTEX_ATTRIB: {
7254 const Vec4& value = state_.attrib_values[index];
7255 params[0] = value.v[0];
7256 params[1] = value.v[1];
7257 params[2] = value.v[2];
7258 params[3] = value.v[3];
7263 GetVertexAttribHelper(attrib, pname, &value);
7264 *params = static_cast<GLfloat>(value);
7270 void GLES2DecoderImpl::DoGetVertexAttribiv(
7271 GLuint index, GLenum pname, GLint* params) {
7272 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7275 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7279 case GL_CURRENT_VERTEX_ATTRIB: {
7280 const Vec4& value = state_.attrib_values[index];
7281 params[0] = static_cast<GLint>(value.v[0]);
7282 params[1] = static_cast<GLint>(value.v[1]);
7283 params[2] = static_cast<GLint>(value.v[2]);
7284 params[3] = static_cast<GLint>(value.v[3]);
7288 GetVertexAttribHelper(attrib, pname, params);
7293 bool GLES2DecoderImpl::SetVertexAttribValue(
7294 const char* function_name, GLuint index, const GLfloat* value) {
7295 if (index >= state_.attrib_values.size()) {
7296 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7299 Vec4& v = state_.attrib_values[index];
7307 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7308 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7309 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7310 glVertexAttrib1f(index, v0);
7314 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7315 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7316 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7317 glVertexAttrib2f(index, v0, v1);
7321 void GLES2DecoderImpl::DoVertexAttrib3f(
7322 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7323 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7324 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7325 glVertexAttrib3f(index, v0, v1, v2);
7329 void GLES2DecoderImpl::DoVertexAttrib4f(
7330 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7331 GLfloat v[4] = { v0, v1, v2, v3, };
7332 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7333 glVertexAttrib4f(index, v0, v1, v2, v3);
7337 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7338 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7339 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7340 glVertexAttrib1fv(index, v);
7344 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7345 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7346 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7347 glVertexAttrib2fv(index, v);
7351 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7352 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7353 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7354 glVertexAttrib3fv(index, v);
7358 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7359 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7360 glVertexAttrib4fv(index, v);
7364 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7365 uint32 immediate_data_size,
7366 const void* cmd_data) {
7367 const gles2::cmds::VertexAttribPointer& c =
7368 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7370 if (!state_.bound_array_buffer.get() ||
7371 state_.bound_array_buffer->IsDeleted()) {
7372 if (state_.vertex_attrib_manager.get() ==
7373 state_.default_vertex_attrib_manager.get()) {
7375 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7376 return error::kNoError;
7377 } else if (c.offset != 0) {
7380 "glVertexAttribPointer", "client side arrays are not allowed");
7381 return error::kNoError;
7385 GLuint indx = c.indx;
7386 GLint size = c.size;
7387 GLenum type = c.type;
7388 GLboolean normalized = static_cast<GLboolean>(c.normalized);
7389 GLsizei stride = c.stride;
7390 GLsizei offset = c.offset;
7391 const void* ptr = reinterpret_cast<const void*>(offset);
7392 if (!validators_->vertex_attrib_type.IsValid(type)) {
7393 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7394 return error::kNoError;
7396 if (!validators_->vertex_attrib_size.IsValid(size)) {
7398 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7399 return error::kNoError;
7401 if (indx >= group_->max_vertex_attribs()) {
7403 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7404 return error::kNoError;
7408 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7409 return error::kNoError;
7413 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7414 return error::kNoError;
7418 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7419 return error::kNoError;
7421 GLsizei component_size =
7422 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7423 // component_size must be a power of two to use & as optimized modulo.
7424 DCHECK(GLES2Util::IsPOT(component_size));
7425 if (offset & (component_size - 1)) {
7427 GL_INVALID_OPERATION,
7428 "glVertexAttribPointer", "offset not valid for type");
7429 return error::kNoError;
7431 if (stride & (component_size - 1)) {
7433 GL_INVALID_OPERATION,
7434 "glVertexAttribPointer", "stride not valid for type");
7435 return error::kNoError;
7437 state_.vertex_attrib_manager
7438 ->SetAttribInfo(indx,
7439 state_.bound_array_buffer.get(),
7444 stride != 0 ? stride : component_size * size,
7446 if (type != GL_FIXED) {
7447 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7449 return error::kNoError;
7452 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7454 state_.viewport_x = x;
7455 state_.viewport_y = y;
7456 state_.viewport_width = std::min(width, viewport_max_width_);
7457 state_.viewport_height = std::min(height, viewport_max_height_);
7458 glViewport(x, y, width, height);
7461 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7462 uint32 immediate_data_size,
7463 const void* cmd_data) {
7464 const gles2::cmds::VertexAttribDivisorANGLE& c =
7465 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
7466 if (!features().angle_instanced_arrays) {
7468 GL_INVALID_OPERATION,
7469 "glVertexAttribDivisorANGLE", "function not available");
7470 return error::kNoError;
7472 GLuint index = c.index;
7473 GLuint divisor = c.divisor;
7474 if (index >= group_->max_vertex_attribs()) {
7477 "glVertexAttribDivisorANGLE", "index out of range");
7478 return error::kNoError;
7481 state_.vertex_attrib_manager->SetDivisor(
7484 glVertexAttribDivisorANGLE(index, divisor);
7485 return error::kNoError;
7488 template <typename pixel_data_type>
7489 static void WriteAlphaData(
7490 void *pixels, uint32 row_count, uint32 channel_count,
7491 uint32 alpha_channel_index, uint32 unpadded_row_size,
7492 uint32 padded_row_size, pixel_data_type alpha_value) {
7493 DCHECK_GT(channel_count, 0U);
7494 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7495 uint32 unpadded_row_size_in_elements =
7496 unpadded_row_size / sizeof(pixel_data_type);
7497 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7498 uint32 padded_row_size_in_elements =
7499 padded_row_size / sizeof(pixel_data_type);
7500 pixel_data_type* dst =
7501 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7502 for (uint32 yy = 0; yy < row_count; ++yy) {
7503 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7504 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7507 dst += padded_row_size_in_elements;
7511 void GLES2DecoderImpl::FinishReadPixels(
7512 const cmds::ReadPixels& c,
7514 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7515 GLsizei width = c.width;
7516 GLsizei height = c.height;
7517 GLenum format = c.format;
7518 GLenum type = c.type;
7519 typedef cmds::ReadPixels::Result Result;
7521 Result* result = NULL;
7522 if (c.result_shm_id != 0) {
7523 result = GetSharedMemoryAs<Result*>(
7524 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7527 glDeleteBuffersARB(1, &buffer);
7532 GLES2Util::ComputeImageDataSizes(
7533 width, height, format, type, state_.pack_alignment, &pixels_size,
7535 void* pixels = GetSharedMemoryAs<void*>(
7536 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7539 glDeleteBuffersARB(1, &buffer);
7545 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7547 if (features().map_buffer_range) {
7548 data = glMapBufferRange(
7549 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7551 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7553 memcpy(pixels, data, pixels_size);
7554 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7555 // have to restore the state.
7556 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7557 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7558 glDeleteBuffersARB(1, &buffer);
7561 if (result != NULL) {
7565 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7566 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7567 if ((channels_exist & 0x0008) == 0 &&
7568 workarounds().clear_alpha_in_readpixels) {
7569 // Set the alpha to 255 because some drivers are buggy in this regard.
7572 uint32 unpadded_row_size;
7573 uint32 padded_row_size;
7574 if (!GLES2Util::ComputeImageDataSizes(
7575 width, 2, format, type, state_.pack_alignment, &temp_size,
7576 &unpadded_row_size, &padded_row_size)) {
7580 uint32 channel_count = 0;
7581 uint32 alpha_channel = 0;
7594 if (channel_count > 0) {
7596 case GL_UNSIGNED_BYTE:
7597 WriteAlphaData<uint8>(
7598 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7599 padded_row_size, 0xFF);
7602 WriteAlphaData<float>(
7603 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7604 padded_row_size, 1.0f);
7607 WriteAlphaData<uint16>(
7608 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7609 padded_row_size, 0x3C00);
7616 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
7617 const void* cmd_data) {
7618 const gles2::cmds::ReadPixels& c =
7619 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
7620 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7621 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7622 if (fbo_error != error::kNoError)
7626 GLsizei width = c.width;
7627 GLsizei height = c.height;
7628 GLenum format = c.format;
7629 GLenum type = c.type;
7630 GLboolean async = static_cast<GLboolean>(c.async);
7631 if (width < 0 || height < 0) {
7632 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7633 return error::kNoError;
7635 typedef cmds::ReadPixels::Result Result;
7637 if (!GLES2Util::ComputeImageDataSizes(
7638 width, height, format, type, state_.pack_alignment, &pixels_size,
7640 return error::kOutOfBounds;
7642 void* pixels = GetSharedMemoryAs<void*>(
7643 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7645 return error::kOutOfBounds;
7647 Result* result = NULL;
7648 if (c.result_shm_id != 0) {
7649 result = GetSharedMemoryAs<Result*>(
7650 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7652 return error::kOutOfBounds;
7656 if (!validators_->read_pixel_format.IsValid(format)) {
7657 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7658 return error::kNoError;
7660 if (!validators_->read_pixel_type.IsValid(type)) {
7661 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7662 return error::kNoError;
7664 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7665 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7666 // format and type are acceptable enums but not guaranteed to be supported
7667 // for this framebuffer. Have to ask gl if they are valid.
7668 GLint preferred_format = 0;
7669 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7670 GLint preferred_type = 0;
7671 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7672 if (format != static_cast<GLenum>(preferred_format) ||
7673 type != static_cast<GLenum>(preferred_type)) {
7675 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7676 "with the current read framebuffer");
7677 return error::kNoError;
7680 if (width == 0 || height == 0) {
7681 return error::kNoError;
7684 // Get the size of the current fbo or backbuffer.
7685 gfx::Size max_size = GetBoundReadFrameBufferSize();
7689 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7691 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7692 return error::kNoError;
7695 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7696 return error::kNoError;
7699 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7700 return error::kNoError;
7703 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7705 ScopedResolvedFrameBufferBinder binder(this, false, true);
7707 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7708 // The user requested an out of range area. Get the results 1 line
7711 uint32 unpadded_row_size;
7712 uint32 padded_row_size;
7713 if (!GLES2Util::ComputeImageDataSizes(
7714 width, 2, format, type, state_.pack_alignment, &temp_size,
7715 &unpadded_row_size, &padded_row_size)) {
7717 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7718 return error::kNoError;
7721 GLint dest_x_offset = std::max(-x, 0);
7722 uint32 dest_row_offset;
7723 if (!GLES2Util::ComputeImageDataSizes(
7724 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7727 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7728 return error::kNoError;
7731 // Copy each row into the larger dest rect.
7732 int8* dst = static_cast<int8*>(pixels);
7733 GLint read_x = std::max(0, x);
7734 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7735 GLint read_width = read_end_x - read_x;
7736 for (GLint yy = 0; yy < height; ++yy) {
7740 memset(dst, 0, unpadded_row_size);
7742 // If the row is in range, copy it.
7743 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7745 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7747 dst += padded_row_size;
7750 if (async && features().use_async_readpixels) {
7752 glGenBuffersARB(1, &buffer);
7753 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7754 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7755 GLenum error = glGetError();
7756 if (error == GL_NO_ERROR) {
7757 glReadPixels(x, y, width, height, format, type, 0);
7758 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7759 new FenceCallback()));
7760 WaitForReadPixels(base::Bind(
7761 &GLES2DecoderImpl::FinishReadPixels,
7762 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7763 <GLES2DecoderImpl>(this),
7765 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7766 return error::kNoError;
7768 // On error, unbind pack buffer and fall through to sync readpixels
7769 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7772 glReadPixels(x, y, width, height, format, type, pixels);
7774 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7775 if (error == GL_NO_ERROR) {
7776 if (result != NULL) {
7779 FinishReadPixels(c, 0);
7782 return error::kNoError;
7785 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
7786 const void* cmd_data) {
7787 const gles2::cmds::PixelStorei& c =
7788 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
7789 GLenum pname = c.pname;
7790 GLenum param = c.param;
7791 if (!validators_->pixel_store.IsValid(pname)) {
7792 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7793 return error::kNoError;
7796 case GL_PACK_ALIGNMENT:
7797 case GL_UNPACK_ALIGNMENT:
7798 if (!validators_->pixel_store_alignment.IsValid(param)) {
7800 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7801 return error::kNoError;
7804 case GL_UNPACK_FLIP_Y_CHROMIUM:
7805 unpack_flip_y_ = (param != 0);
7806 return error::kNoError;
7807 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7808 unpack_premultiply_alpha_ = (param != 0);
7809 return error::kNoError;
7810 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7811 unpack_unpremultiply_alpha_ = (param != 0);
7812 return error::kNoError;
7816 glPixelStorei(pname, param);
7818 case GL_PACK_ALIGNMENT:
7819 state_.pack_alignment = param;
7821 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7822 state_.pack_reverse_row_order = (param != 0);
7824 case GL_UNPACK_ALIGNMENT:
7825 state_.unpack_alignment = param;
7828 // Validation should have prevented us from getting here.
7832 return error::kNoError;
7835 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7836 uint32 immediate_data_size,
7837 const void* cmd_data) {
7838 const gles2::cmds::PostSubBufferCHROMIUM& c =
7839 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
7840 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7842 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7844 if (!supports_post_sub_buffer_) {
7846 GL_INVALID_OPERATION,
7847 "glPostSubBufferCHROMIUM", "command not supported by surface");
7848 return error::kNoError;
7851 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7854 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7855 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7856 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7857 is_offscreen ? offscreen_size_ : surface_->GetSize());
7859 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7860 return error::kNoError;
7862 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7863 return error::kLostContext;
7867 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7868 uint32 immediate_data_size,
7869 const void* cmd_data) {
7870 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
7871 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
7872 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
7874 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
7875 "glScheduleOverlayPlaneCHROMIUM",
7877 return error::kNoError;
7879 gfx::GLImage* image =
7880 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
7882 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
7883 "glScheduleOverlayPlaneCHROMIUM",
7884 "unsupported texture format");
7885 return error::kNoError;
7887 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
7888 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
7889 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
7890 "glScheduleOverlayPlaneCHROMIUM",
7891 "invalid transform enum");
7892 return error::kNoError;
7894 if (!surface_->ScheduleOverlayPlane(
7898 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
7899 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
7900 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
7901 "glScheduleOverlayPlaneCHROMIUM",
7902 "failed to schedule overlay");
7904 return error::kNoError;
7907 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7908 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7909 const std::string& name_str) {
7910 if (!StringIsValidForGLES(name_str.c_str())) {
7912 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7913 return error::kNoError;
7915 Program* program = GetProgramInfoNotShader(
7916 client_id, "glGetAttribLocation");
7918 return error::kNoError;
7920 if (!program->IsValid()) {
7922 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7923 return error::kNoError;
7925 GLint* location = GetSharedMemoryAs<GLint*>(
7926 location_shm_id, location_shm_offset, sizeof(GLint));
7928 return error::kOutOfBounds;
7930 // Require the client to init this incase the context is lost and we are no
7931 // longer executing commands.
7932 if (*location != -1) {
7933 return error::kGenericError;
7935 *location = program->GetAttribLocation(name_str);
7936 return error::kNoError;
7939 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7940 uint32 immediate_data_size,
7941 const void* cmd_data) {
7942 const gles2::cmds::GetAttribLocation& c =
7943 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
7944 Bucket* bucket = GetBucket(c.name_bucket_id);
7946 return error::kInvalidArguments;
7948 std::string name_str;
7949 if (!bucket->GetAsString(&name_str)) {
7950 return error::kInvalidArguments;
7952 return GetAttribLocationHelper(
7953 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7956 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7957 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7958 const std::string& name_str) {
7959 if (!StringIsValidForGLES(name_str.c_str())) {
7961 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7962 return error::kNoError;
7964 Program* program = GetProgramInfoNotShader(
7965 client_id, "glGetUniformLocation");
7967 return error::kNoError;
7969 if (!program->IsValid()) {
7971 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7972 return error::kNoError;
7974 GLint* location = GetSharedMemoryAs<GLint*>(
7975 location_shm_id, location_shm_offset, sizeof(GLint));
7977 return error::kOutOfBounds;
7979 // Require the client to init this incase the context is lost an we are no
7980 // longer executing commands.
7981 if (*location != -1) {
7982 return error::kGenericError;
7984 *location = program->GetUniformFakeLocation(name_str);
7985 return error::kNoError;
7988 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7989 uint32 immediate_data_size,
7990 const void* cmd_data) {
7991 const gles2::cmds::GetUniformLocation& c =
7992 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
7993 Bucket* bucket = GetBucket(c.name_bucket_id);
7995 return error::kInvalidArguments;
7997 std::string name_str;
7998 if (!bucket->GetAsString(&name_str)) {
7999 return error::kInvalidArguments;
8001 return GetUniformLocationHelper(
8002 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8005 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8006 const void* cmd_data) {
8007 const gles2::cmds::GetString& c =
8008 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8009 GLenum name = static_cast<GLenum>(c.name);
8010 if (!validators_->string_type.IsValid(name)) {
8011 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8012 return error::kNoError;
8014 const char* str = reinterpret_cast<const char*>(glGetString(name));
8015 std::string extensions;
8018 str = "OpenGL ES 2.0 Chromium";
8020 case GL_SHADING_LANGUAGE_VERSION:
8021 str = "OpenGL ES GLSL ES 1.0 Chromium";
8025 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8026 // They are used by WEBGL_debug_renderer_info.
8027 if (!force_webgl_glsl_validation_)
8032 // For WebGL contexts, strip out the OES derivatives and
8033 // EXT frag depth extensions if they have not been enabled.
8034 if (force_webgl_glsl_validation_) {
8035 extensions = feature_info_->extensions();
8036 if (!derivatives_explicitly_enabled_) {
8037 size_t offset = extensions.find(kOESDerivativeExtension);
8038 if (std::string::npos != offset) {
8039 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8043 if (!frag_depth_explicitly_enabled_) {
8044 size_t offset = extensions.find(kEXTFragDepthExtension);
8045 if (std::string::npos != offset) {
8046 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8050 if (!draw_buffers_explicitly_enabled_) {
8051 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8052 if (std::string::npos != offset) {
8053 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8057 if (!shader_texture_lod_explicitly_enabled_) {
8058 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8059 if (std::string::npos != offset) {
8060 extensions.replace(offset,
8061 arraysize(kEXTShaderTextureLodExtension),
8066 extensions = feature_info_->extensions().c_str();
8068 if (supports_post_sub_buffer_)
8069 extensions += " GL_CHROMIUM_post_sub_buffer";
8070 str = extensions.c_str();
8076 Bucket* bucket = CreateBucket(c.bucket_id);
8077 bucket->SetFromString(str);
8078 return error::kNoError;
8081 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8082 const void* cmd_data) {
8083 const gles2::cmds::BufferData& c =
8084 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8085 GLenum target = static_cast<GLenum>(c.target);
8086 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8087 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8088 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8089 GLenum usage = static_cast<GLenum>(c.usage);
8090 const void* data = NULL;
8091 if (data_shm_id != 0 || data_shm_offset != 0) {
8092 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8094 return error::kOutOfBounds;
8097 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8098 return error::kNoError;
8101 void GLES2DecoderImpl::DoBufferSubData(
8102 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8103 // Just delegate it. Some validation is actually done before this.
8104 buffer_manager()->ValidateAndDoBufferSubData(
8105 &state_, target, offset, size, data);
8108 bool GLES2DecoderImpl::ClearLevel(
8109 unsigned service_id,
8110 unsigned bind_target,
8113 unsigned internal_format,
8118 bool is_texture_immutable) {
8119 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8120 if (feature_info_->feature_flags().angle_depth_texture &&
8121 (channels & GLES2Util::kDepth) != 0) {
8122 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8123 // on depth formats.
8125 glGenFramebuffersEXT(1, &fb);
8126 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8128 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8129 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8130 GL_DEPTH_ATTACHMENT;
8132 glFramebufferTexture2DEXT(
8133 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
8134 // ANGLE promises a depth only attachment ok.
8135 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8136 GL_FRAMEBUFFER_COMPLETE) {
8140 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8141 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8143 state_.SetDeviceDepthMask(GL_TRUE);
8144 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8145 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8147 RestoreClearState();
8149 glDeleteFramebuffersEXT(1, &fb);
8150 Framebuffer* framebuffer =
8151 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8152 GLuint fb_service_id =
8153 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8154 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8158 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8161 uint32 padded_row_size;
8162 if (!GLES2Util::ComputeImageDataSizes(
8163 width, height, format, type, state_.unpack_alignment, &size,
8164 NULL, &padded_row_size)) {
8168 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8172 if (size > kMaxZeroSize) {
8173 if (kMaxZeroSize < padded_row_size) {
8174 // That'd be an awfully large texture.
8177 // We should never have a large total size with a zero row size.
8178 DCHECK_GT(padded_row_size, 0U);
8179 tile_height = kMaxZeroSize / padded_row_size;
8180 if (!GLES2Util::ComputeImageDataSizes(
8181 width, tile_height, format, type, state_.unpack_alignment, &size,
8186 tile_height = height;
8189 // Assumes the size has already been checked.
8190 scoped_ptr<char[]> zero(new char[size]);
8191 memset(zero.get(), 0, size);
8192 glBindTexture(bind_target, service_id);
8195 while (y < height) {
8196 GLint h = y + tile_height > height ? height - y : tile_height;
8197 if (is_texture_immutable || h != height) {
8198 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8201 target, level, internal_format, width, h, 0, format, type,
8206 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
8207 &state_, bind_target);
8208 glBindTexture(bind_target, texture ? texture->service_id() : 0);
8214 const int kS3TCBlockWidth = 4;
8215 const int kS3TCBlockHeight = 4;
8216 const int kS3TCDXT1BlockSize = 8;
8217 const int kS3TCDXT3AndDXT5BlockSize = 16;
8219 bool IsValidDXTSize(GLint level, GLsizei size) {
8220 return (size == 1) ||
8221 (size == 2) || !(size % kS3TCBlockWidth);
8224 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8225 return GLES2Util::IsPOT(size);
8228 } // anonymous namespace.
8230 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8231 const char* function_name,
8232 GLsizei width, GLsizei height, GLenum format, size_t size) {
8233 unsigned int bytes_required = 0;
8236 case GL_ATC_RGB_AMD:
8237 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8238 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8239 case GL_ETC1_RGB8_OES: {
8240 int num_blocks_across =
8241 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8242 int num_blocks_down =
8243 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8244 int num_blocks = num_blocks_across * num_blocks_down;
8245 bytes_required = num_blocks * kS3TCDXT1BlockSize;
8248 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8249 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8250 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8251 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8252 int num_blocks_across =
8253 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8254 int num_blocks_down =
8255 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8256 int num_blocks = num_blocks_across * num_blocks_down;
8257 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
8260 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8261 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
8262 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
8265 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8266 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8267 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
8271 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8275 if (size != bytes_required) {
8277 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8284 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8285 const char* function_name,
8286 GLint level, GLsizei width, GLsizei height, GLenum format) {
8288 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8289 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8290 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8291 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8292 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8294 GL_INVALID_OPERATION, function_name,
8295 "width or height invalid for level");
8300 case GL_ATC_RGB_AMD:
8301 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8302 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8303 case GL_ETC1_RGB8_OES: {
8304 if (width <= 0 || height <= 0) {
8306 GL_INVALID_OPERATION, function_name,
8307 "width or height invalid for level");
8312 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8313 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8314 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8315 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8316 if (!IsValidPVRTCSize(level, width) ||
8317 !IsValidPVRTCSize(level, height)) {
8319 GL_INVALID_OPERATION, function_name,
8320 "width or height invalid for level");
8330 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8331 const char* function_name,
8332 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8333 GLsizei width, GLsizei height, GLenum format,
8335 if (xoffset < 0 || yoffset < 0) {
8337 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8342 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8343 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8344 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8345 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8346 const int kBlockWidth = 4;
8347 const int kBlockHeight = 4;
8348 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8350 GL_INVALID_OPERATION, function_name,
8351 "xoffset or yoffset not multiple of 4");
8354 GLsizei tex_width = 0;
8355 GLsizei tex_height = 0;
8356 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8357 width - xoffset > tex_width ||
8358 height - yoffset > tex_height) {
8360 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8363 return ValidateCompressedTexDimensions(
8364 function_name, level, width, height, format);
8366 case GL_ATC_RGB_AMD:
8367 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8368 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8370 GL_INVALID_OPERATION, function_name,
8371 "not supported for ATC textures");
8374 case GL_ETC1_RGB8_OES: {
8376 GL_INVALID_OPERATION, function_name,
8377 "not supported for ECT1_RGB8_OES textures");
8380 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8381 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8382 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8383 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8384 if ((xoffset != 0) || (yoffset != 0)) {
8386 GL_INVALID_OPERATION, function_name,
8387 "xoffset and yoffset must be zero");
8390 GLsizei tex_width = 0;
8391 GLsizei tex_height = 0;
8392 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8393 width != tex_width ||
8394 height != tex_height) {
8396 GL_INVALID_OPERATION, function_name,
8397 "dimensions must match existing texture level dimensions");
8400 return ValidateCompressedTexDimensions(
8401 function_name, level, width, height, format);
8408 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8411 GLenum internal_format,
8417 // TODO(gman): Validate image_size is correct for width, height and format.
8418 if (!validators_->texture_target.IsValid(target)) {
8419 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8420 "glCompressedTexImage2D", target, "target");
8421 return error::kNoError;
8423 if (!validators_->compressed_texture_format.IsValid(
8425 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8426 "glCompressedTexImage2D", internal_format, "internal_format");
8427 return error::kNoError;
8429 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8433 "glCompressedTexImage2D", "dimensions out of range");
8434 return error::kNoError;
8436 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8441 "glCompressedTexImage2D", "unknown texture target");
8442 return error::kNoError;
8444 Texture* texture = texture_ref->texture();
8445 if (texture->IsImmutable()) {
8447 GL_INVALID_OPERATION,
8448 "glCompressedTexImage2D", "texture is immutable");
8449 return error::kNoError;
8452 if (!ValidateCompressedTexDimensions(
8453 "glCompressedTexImage2D", level, width, height, internal_format) ||
8454 !ValidateCompressedTexFuncData(
8455 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8456 return error::kNoError;
8459 if (!EnsureGPUMemoryAvailable(image_size)) {
8461 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8462 return error::kNoError;
8465 if (texture->IsAttachedToFramebuffer()) {
8466 framebuffer_state_.clear_state_dirty = true;
8469 scoped_ptr<int8[]> zero;
8471 zero.reset(new int8[image_size]);
8472 memset(zero.get(), 0, image_size);
8475 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8476 glCompressedTexImage2D(
8477 target, level, internal_format, width, height, border, image_size, data);
8478 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8479 if (error == GL_NO_ERROR) {
8480 texture_manager()->SetLevelInfo(
8481 texture_ref, target, level, internal_format,
8482 width, height, 1, border, 0, 0, true);
8485 // This may be a slow command. Exit command processing to allow for
8486 // context preemption and GPU watchdog checks.
8487 ExitCommandProcessingEarly();
8488 return error::kNoError;
8491 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8492 uint32 immediate_data_size,
8493 const void* cmd_data) {
8494 const gles2::cmds::CompressedTexImage2D& c =
8495 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
8496 GLenum target = static_cast<GLenum>(c.target);
8497 GLint level = static_cast<GLint>(c.level);
8498 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8499 GLsizei width = static_cast<GLsizei>(c.width);
8500 GLsizei height = static_cast<GLsizei>(c.height);
8501 GLint border = static_cast<GLint>(c.border);
8502 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8503 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8504 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8505 const void* data = NULL;
8506 if (data_shm_id != 0 || data_shm_offset != 0) {
8507 data = GetSharedMemoryAs<const void*>(
8508 data_shm_id, data_shm_offset, image_size);
8510 return error::kOutOfBounds;
8513 return DoCompressedTexImage2D(
8514 target, level, internal_format, width, height, border, image_size, data);
8517 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8518 uint32 immediate_data_size,
8519 const void* cmd_data) {
8520 const gles2::cmds::CompressedTexImage2DBucket& c =
8521 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
8522 GLenum target = static_cast<GLenum>(c.target);
8523 GLint level = static_cast<GLint>(c.level);
8524 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8525 GLsizei width = static_cast<GLsizei>(c.width);
8526 GLsizei height = static_cast<GLsizei>(c.height);
8527 GLint border = static_cast<GLint>(c.border);
8528 Bucket* bucket = GetBucket(c.bucket_id);
8530 return error::kInvalidArguments;
8532 uint32 data_size = bucket->size();
8533 GLsizei imageSize = data_size;
8534 const void* data = bucket->GetData(0, data_size);
8536 return error::kInvalidArguments;
8538 return DoCompressedTexImage2D(
8539 target, level, internal_format, width, height, border,
8543 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8544 uint32 immediate_data_size,
8545 const void* cmd_data) {
8546 const gles2::cmds::CompressedTexSubImage2DBucket& c =
8547 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
8548 GLenum target = static_cast<GLenum>(c.target);
8549 GLint level = static_cast<GLint>(c.level);
8550 GLint xoffset = static_cast<GLint>(c.xoffset);
8551 GLint yoffset = static_cast<GLint>(c.yoffset);
8552 GLsizei width = static_cast<GLsizei>(c.width);
8553 GLsizei height = static_cast<GLsizei>(c.height);
8554 GLenum format = static_cast<GLenum>(c.format);
8555 Bucket* bucket = GetBucket(c.bucket_id);
8557 return error::kInvalidArguments;
8559 uint32 data_size = bucket->size();
8560 GLsizei imageSize = data_size;
8561 const void* data = bucket->GetData(0, data_size);
8563 return error::kInvalidArguments;
8565 if (!validators_->texture_target.IsValid(target)) {
8567 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8568 return error::kNoError;
8570 if (!validators_->compressed_texture_format.IsValid(format)) {
8571 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8572 "glCompressedTexSubImage2D", format, "format");
8573 return error::kNoError;
8577 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8578 return error::kNoError;
8582 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8583 return error::kNoError;
8585 if (imageSize < 0) {
8587 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8588 return error::kNoError;
8590 DoCompressedTexSubImage2D(
8591 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8592 return error::kNoError;
8595 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
8596 const void* cmd_data) {
8597 const gles2::cmds::TexImage2D& c =
8598 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
8599 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8600 "width", c.width, "height", c.height);
8601 // Set as failed for now, but if it successed, this will be set to not failed.
8602 texture_state_.tex_image_2d_failed = true;
8603 GLenum target = static_cast<GLenum>(c.target);
8604 GLint level = static_cast<GLint>(c.level);
8605 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8606 // for internalformat.
8607 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8608 GLsizei width = static_cast<GLsizei>(c.width);
8609 GLsizei height = static_cast<GLsizei>(c.height);
8610 GLint border = static_cast<GLint>(c.border);
8611 GLenum format = static_cast<GLenum>(c.format);
8612 GLenum type = static_cast<GLenum>(c.type);
8613 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8614 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8616 if (!GLES2Util::ComputeImageDataSizes(
8617 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8619 return error::kOutOfBounds;
8621 const void* pixels = NULL;
8622 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8623 pixels = GetSharedMemoryAs<const void*>(
8624 pixels_shm_id, pixels_shm_offset, pixels_size);
8626 return error::kOutOfBounds;
8630 TextureManager::DoTextImage2DArguments args = {
8631 target, level, internal_format, width, height, border, format, type,
8632 pixels, pixels_size};
8633 texture_manager()->ValidateAndDoTexImage2D(
8634 &texture_state_, &state_, &framebuffer_state_, args);
8636 // This may be a slow command. Exit command processing to allow for
8637 // context preemption and GPU watchdog checks.
8638 ExitCommandProcessingEarly();
8639 return error::kNoError;
8642 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8651 const void * data) {
8652 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8656 GL_INVALID_OPERATION,
8657 "glCompressedTexSubImage2D", "unknown texture for target");
8660 Texture* texture = texture_ref->texture();
8662 GLenum internal_format = 0;
8663 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8665 GL_INVALID_OPERATION,
8666 "glCompressedTexSubImage2D", "level does not exist.");
8669 if (internal_format != format) {
8671 GL_INVALID_OPERATION,
8672 "glCompressedTexSubImage2D", "format does not match internal format.");
8675 if (!texture->ValidForTexture(
8676 target, level, xoffset, yoffset, width, height, type)) {
8678 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8682 if (!ValidateCompressedTexFuncData(
8683 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8684 !ValidateCompressedTexSubDimensions(
8685 "glCompressedTexSubImage2D",
8686 target, level, xoffset, yoffset, width, height, format, texture)) {
8691 // Note: There is no need to deal with texture cleared tracking here
8692 // because the validation above means you can only get here if the level
8693 // is already a matching compressed format and in that case
8694 // CompressedTexImage2D already cleared the texture.
8695 glCompressedTexSubImage2D(
8696 target, level, xoffset, yoffset, width, height, format, image_size, data);
8698 // This may be a slow command. Exit command processing to allow for
8699 // context preemption and GPU watchdog checks.
8700 ExitCommandProcessingEarly();
8704 GLint start, GLint range, GLint sourceRange,
8705 GLint* out_start, GLint* out_range) {
8712 GLint end = start + range;
8713 if (end > sourceRange) {
8714 range -= end - sourceRange;
8720 void GLES2DecoderImpl::DoCopyTexImage2D(
8723 GLenum internal_format,
8729 DCHECK(!ShouldDeferReads());
8730 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8734 GL_INVALID_OPERATION,
8735 "glCopyTexImage2D", "unknown texture for target");
8738 Texture* texture = texture_ref->texture();
8739 if (texture->IsImmutable()) {
8741 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8744 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8747 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8750 if (!texture_manager()->ValidateFormatAndTypeCombination(
8751 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8752 GL_UNSIGNED_BYTE)) {
8756 // Check we have compatible formats.
8757 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8758 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8759 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8761 if ((channels_needed & channels_exist) != channels_needed) {
8763 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8767 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8769 GL_INVALID_OPERATION,
8770 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8774 uint32 estimated_size = 0;
8775 if (!GLES2Util::ComputeImageDataSizes(
8776 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8777 &estimated_size, NULL, NULL)) {
8779 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8783 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8784 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8788 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
8792 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
8794 GL_INVALID_OPERATION,
8795 "glCopyTexImage2D", "source and destination textures are the same");
8799 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8803 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8804 ScopedResolvedFrameBufferBinder binder(this, false, true);
8805 gfx::Size size = GetBoundReadFrameBufferSize();
8807 if (texture->IsAttachedToFramebuffer()) {
8808 framebuffer_state_.clear_state_dirty = true;
8811 // Clip to size to source dimensions
8814 GLint copyWidth = 0;
8815 GLint copyHeight = 0;
8816 Clip(x, width, size.width(), ©X, ©Width);
8817 Clip(y, height, size.height(), ©Y, ©Height);
8821 copyWidth != width ||
8822 copyHeight != height) {
8823 // some part was clipped so clear the texture.
8825 texture->service_id(), texture->target(),
8826 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8827 width, height, texture->IsImmutable())) {
8829 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8832 if (copyHeight > 0 && copyWidth > 0) {
8833 GLint dx = copyX - x;
8834 GLint dy = copyY - y;
8837 ScopedModifyPixels modify(texture_ref);
8838 glCopyTexSubImage2D(target, level,
8839 destX, destY, copyX, copyY,
8840 copyWidth, copyHeight);
8843 ScopedModifyPixels modify(texture_ref);
8844 glCopyTexImage2D(target, level, internal_format,
8845 copyX, copyY, copyWidth, copyHeight, border);
8847 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8848 if (error == GL_NO_ERROR) {
8849 texture_manager()->SetLevelInfo(
8850 texture_ref, target, level, internal_format, width, height, 1,
8851 border, internal_format, GL_UNSIGNED_BYTE, true);
8854 // This may be a slow command. Exit command processing to allow for
8855 // context preemption and GPU watchdog checks.
8856 ExitCommandProcessingEarly();
8859 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8868 DCHECK(!ShouldDeferReads());
8869 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8873 GL_INVALID_OPERATION,
8874 "glCopyTexSubImage2D", "unknown texture for target");
8877 Texture* texture = texture_ref->texture();
8880 if (!texture->GetLevelType(target, level, &type, &format) ||
8881 !texture->ValidForTexture(
8882 target, level, xoffset, yoffset, width, height, type)) {
8884 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8887 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8889 GL_INVALID_OPERATION,
8890 "glCopyTexSubImage2D", "async upload pending for texture");
8894 // Check we have compatible formats.
8895 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8896 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8897 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8899 if (!channels_needed ||
8900 (channels_needed & channels_exist) != channels_needed) {
8902 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8906 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8908 GL_INVALID_OPERATION,
8909 "glCopySubImage2D", "can not be used with depth or stencil textures");
8913 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
8917 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
8919 GL_INVALID_OPERATION,
8920 "glCopyTexSubImage2D", "source and destination textures are the same");
8924 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8928 ScopedResolvedFrameBufferBinder binder(this, false, true);
8929 gfx::Size size = GetBoundReadFrameBufferSize();
8932 GLint copyWidth = 0;
8933 GLint copyHeight = 0;
8934 Clip(x, width, size.width(), ©X, ©Width);
8935 Clip(y, height, size.height(), ©Y, ©Height);
8937 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8939 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8945 copyWidth != width ||
8946 copyHeight != height) {
8947 // some part was clipped so clear the sub rect.
8948 uint32 pixels_size = 0;
8949 if (!GLES2Util::ComputeImageDataSizes(
8950 width, height, format, type, state_.unpack_alignment, &pixels_size,
8953 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8956 scoped_ptr<char[]> zero(new char[pixels_size]);
8957 memset(zero.get(), 0, pixels_size);
8958 ScopedModifyPixels modify(texture_ref);
8960 target, level, xoffset, yoffset, width, height,
8961 format, type, zero.get());
8964 if (copyHeight > 0 && copyWidth > 0) {
8965 GLint dx = copyX - x;
8966 GLint dy = copyY - y;
8967 GLint destX = xoffset + dx;
8968 GLint destY = yoffset + dy;
8969 ScopedModifyPixels modify(texture_ref);
8970 glCopyTexSubImage2D(target, level,
8971 destX, destY, copyX, copyY,
8972 copyWidth, copyHeight);
8975 // This may be a slow command. Exit command processing to allow for
8976 // context preemption and GPU watchdog checks.
8977 ExitCommandProcessingEarly();
8980 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8981 error::Error* error,
8982 const char* function_name,
8991 const void * data) {
8992 (*error) = error::kNoError;
8993 if (!validators_->texture_target.IsValid(target)) {
8994 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8998 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
9002 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
9005 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9009 GL_INVALID_OPERATION,
9010 function_name, "unknown texture for target");
9013 Texture* texture = texture_ref->texture();
9014 GLenum current_type = 0;
9015 GLenum internal_format = 0;
9016 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
9018 GL_INVALID_OPERATION, function_name, "level does not exist.");
9021 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
9022 function_name, format, type, internal_format, level)) {
9025 if (type != current_type) {
9027 GL_INVALID_OPERATION,
9028 function_name, "type does not match type of texture.");
9031 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9033 GL_INVALID_OPERATION,
9034 function_name, "async upload pending for texture");
9037 if (!texture->ValidForTexture(
9038 target, level, xoffset, yoffset, width, height, type)) {
9039 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
9042 if ((GLES2Util::GetChannelsForFormat(format) &
9043 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9045 GL_INVALID_OPERATION,
9046 function_name, "can not supply data for depth or stencil textures");
9050 (*error) = error::kOutOfBounds;
9056 error::Error GLES2DecoderImpl::DoTexSubImage2D(
9065 const void * data) {
9066 error::Error error = error::kNoError;
9067 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
9068 xoffset, yoffset, width, height, format, type, data)) {
9071 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9073 Texture* texture = texture_ref->texture();
9074 GLsizei tex_width = 0;
9075 GLsizei tex_height = 0;
9076 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
9078 if (xoffset != 0 || yoffset != 0 ||
9079 width != tex_width || height != tex_height) {
9080 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
9083 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
9084 return error::kNoError;
9086 ScopedTextureUploadTimer timer(&texture_state_);
9088 target, level, xoffset, yoffset, width, height, format, type, data);
9089 return error::kNoError;
9092 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
9093 !texture->IsImmutable()) {
9094 ScopedTextureUploadTimer timer(&texture_state_);
9095 GLenum internal_format;
9097 texture->GetLevelType(target, level, &tex_type, &internal_format);
9098 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9101 target, level, internal_format, width, height, 0, format, type, data);
9103 ScopedTextureUploadTimer timer(&texture_state_);
9105 target, level, xoffset, yoffset, width, height, format, type, data);
9107 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9109 // This may be a slow command. Exit command processing to allow for
9110 // context preemption and GPU watchdog checks.
9111 ExitCommandProcessingEarly();
9112 return error::kNoError;
9115 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
9116 const void* cmd_data) {
9117 const gles2::cmds::TexSubImage2D& c =
9118 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
9119 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9120 "width", c.width, "height", c.height);
9121 GLboolean internal = static_cast<GLboolean>(c.internal);
9122 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
9123 return error::kNoError;
9125 GLenum target = static_cast<GLenum>(c.target);
9126 GLint level = static_cast<GLint>(c.level);
9127 GLint xoffset = static_cast<GLint>(c.xoffset);
9128 GLint yoffset = static_cast<GLint>(c.yoffset);
9129 GLsizei width = static_cast<GLsizei>(c.width);
9130 GLsizei height = static_cast<GLsizei>(c.height);
9131 GLenum format = static_cast<GLenum>(c.format);
9132 GLenum type = static_cast<GLenum>(c.type);
9134 if (!GLES2Util::ComputeImageDataSizes(
9135 width, height, format, type, state_.unpack_alignment, &data_size,
9137 return error::kOutOfBounds;
9139 const void* pixels = GetSharedMemoryAs<const void*>(
9140 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9141 return DoTexSubImage2D(
9142 target, level, xoffset, yoffset, width, height, format, type, pixels);
9145 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9146 uint32 immediate_data_size,
9147 const void* cmd_data) {
9148 const gles2::cmds::GetVertexAttribPointerv& c =
9149 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
9150 GLuint index = static_cast<GLuint>(c.index);
9151 GLenum pname = static_cast<GLenum>(c.pname);
9152 typedef cmds::GetVertexAttribPointerv::Result Result;
9153 Result* result = GetSharedMemoryAs<Result*>(
9154 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
9156 return error::kOutOfBounds;
9158 // Check that the client initialized the result.
9159 if (result->size != 0) {
9160 return error::kInvalidArguments;
9162 if (!validators_->vertex_pointer.IsValid(pname)) {
9163 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9164 "glGetVertexAttribPointerv", pname, "pname");
9165 return error::kNoError;
9167 if (index >= group_->max_vertex_attribs()) {
9169 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
9170 return error::kNoError;
9172 result->SetNumResults(1);
9173 *result->GetData() =
9174 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
9175 return error::kNoError;
9178 bool GLES2DecoderImpl::GetUniformSetup(
9179 GLuint program_id, GLint fake_location,
9180 uint32 shm_id, uint32 shm_offset,
9181 error::Error* error, GLint* real_location,
9182 GLuint* service_id, void** result_pointer, GLenum* result_type) {
9185 DCHECK(result_pointer);
9186 DCHECK(result_type);
9187 DCHECK(real_location);
9188 *error = error::kNoError;
9189 // Make sure we have enough room for the result on failure.
9190 SizedResult<GLint>* result;
9191 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9192 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
9194 *error = error::kOutOfBounds;
9197 *result_pointer = result;
9198 // Set the result size to 0 so the client does not have to check for success.
9199 result->SetNumResults(0);
9200 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
9204 if (!program->IsValid()) {
9205 // Program was not linked successfully. (ie, glLinkProgram)
9207 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
9210 *service_id = program->service_id();
9211 GLint array_index = -1;
9212 const Program::UniformInfo* uniform_info =
9213 program->GetUniformInfoByFakeLocation(
9214 fake_location, real_location, &array_index);
9215 if (!uniform_info) {
9216 // No such location.
9218 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
9221 GLenum type = uniform_info->type;
9222 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
9224 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
9227 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9228 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
9230 *error = error::kOutOfBounds;
9233 result->size = size;
9234 *result_type = type;
9238 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
9239 const void* cmd_data) {
9240 const gles2::cmds::GetUniformiv& c =
9241 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
9242 GLuint program = c.program;
9243 GLint fake_location = c.location;
9246 GLint real_location = -1;
9249 if (GetUniformSetup(
9250 program, fake_location, c.params_shm_id, c.params_shm_offset,
9251 &error, &real_location, &service_id, &result, &result_type)) {
9253 service_id, real_location,
9254 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
9259 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
9260 const void* cmd_data) {
9261 const gles2::cmds::GetUniformfv& c =
9262 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
9263 GLuint program = c.program;
9264 GLint fake_location = c.location;
9266 GLint real_location = -1;
9268 typedef cmds::GetUniformfv::Result Result;
9271 if (GetUniformSetup(
9272 program, fake_location, c.params_shm_id, c.params_shm_offset,
9273 &error, &real_location, &service_id,
9274 reinterpret_cast<void**>(&result), &result_type)) {
9275 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
9276 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
9277 GLsizei num_values = result->GetNumResults();
9278 scoped_ptr<GLint[]> temp(new GLint[num_values]);
9279 glGetUniformiv(service_id, real_location, temp.get());
9280 GLfloat* dst = result->GetData();
9281 for (GLsizei ii = 0; ii < num_values; ++ii) {
9282 dst[ii] = (temp[ii] != 0);
9285 glGetUniformfv(service_id, real_location, result->GetData());
9291 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9292 uint32 immediate_data_size,
9293 const void* cmd_data) {
9294 const gles2::cmds::GetShaderPrecisionFormat& c =
9295 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
9296 GLenum shader_type = static_cast<GLenum>(c.shadertype);
9297 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
9298 typedef cmds::GetShaderPrecisionFormat::Result Result;
9299 Result* result = GetSharedMemoryAs<Result*>(
9300 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9302 return error::kOutOfBounds;
9304 // Check that the client initialized the result.
9305 if (result->success != 0) {
9306 return error::kInvalidArguments;
9308 if (!validators_->shader_type.IsValid(shader_type)) {
9309 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9310 "glGetShaderPrecisionFormat", shader_type, "shader_type");
9311 return error::kNoError;
9313 if (!validators_->shader_precision.IsValid(precision_type)) {
9314 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9315 "glGetShaderPrecisionFormat", precision_type, "precision_type");
9316 return error::kNoError;
9319 result->success = 1; // true
9321 GLint range[2] = { 0, 0 };
9322 GLint precision = 0;
9323 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
9325 result->min_range = range[0];
9326 result->max_range = range[1];
9327 result->precision = precision;
9329 return error::kNoError;
9332 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
9333 uint32 immediate_data_size,
9334 const void* cmd_data) {
9335 const gles2::cmds::GetAttachedShaders& c =
9336 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
9337 uint32 result_size = c.result_size;
9338 GLuint program_id = static_cast<GLuint>(c.program);
9339 Program* program = GetProgramInfoNotShader(
9340 program_id, "glGetAttachedShaders");
9342 return error::kNoError;
9344 typedef cmds::GetAttachedShaders::Result Result;
9345 uint32 max_count = Result::ComputeMaxResults(result_size);
9346 Result* result = GetSharedMemoryAs<Result*>(
9347 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
9349 return error::kOutOfBounds;
9351 // Check that the client initialized the result.
9352 if (result->size != 0) {
9353 return error::kInvalidArguments;
9356 glGetAttachedShaders(
9357 program->service_id(), max_count, &count, result->GetData());
9358 for (GLsizei ii = 0; ii < count; ++ii) {
9359 if (!shader_manager()->GetClientId(result->GetData()[ii],
9360 &result->GetData()[ii])) {
9362 return error::kGenericError;
9365 result->SetNumResults(count);
9366 return error::kNoError;
9369 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
9370 uint32 immediate_data_size,
9371 const void* cmd_data) {
9372 const gles2::cmds::GetActiveUniform& c =
9373 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
9374 GLuint program_id = c.program;
9375 GLuint index = c.index;
9376 uint32 name_bucket_id = c.name_bucket_id;
9377 typedef cmds::GetActiveUniform::Result Result;
9378 Result* result = GetSharedMemoryAs<Result*>(
9379 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9381 return error::kOutOfBounds;
9383 // Check that the client initialized the result.
9384 if (result->success != 0) {
9385 return error::kInvalidArguments;
9387 Program* program = GetProgramInfoNotShader(
9388 program_id, "glGetActiveUniform");
9390 return error::kNoError;
9392 const Program::UniformInfo* uniform_info =
9393 program->GetUniformInfo(index);
9394 if (!uniform_info) {
9396 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
9397 return error::kNoError;
9399 result->success = 1; // true.
9400 result->size = uniform_info->size;
9401 result->type = uniform_info->type;
9402 Bucket* bucket = CreateBucket(name_bucket_id);
9403 bucket->SetFromString(uniform_info->name.c_str());
9404 return error::kNoError;
9407 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
9408 const void* cmd_data) {
9409 const gles2::cmds::GetActiveAttrib& c =
9410 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
9411 GLuint program_id = c.program;
9412 GLuint index = c.index;
9413 uint32 name_bucket_id = c.name_bucket_id;
9414 typedef cmds::GetActiveAttrib::Result Result;
9415 Result* result = GetSharedMemoryAs<Result*>(
9416 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9418 return error::kOutOfBounds;
9420 // Check that the client initialized the result.
9421 if (result->success != 0) {
9422 return error::kInvalidArguments;
9424 Program* program = GetProgramInfoNotShader(
9425 program_id, "glGetActiveAttrib");
9427 return error::kNoError;
9429 const Program::VertexAttrib* attrib_info =
9430 program->GetAttribInfo(index);
9433 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9434 return error::kNoError;
9436 result->success = 1; // true.
9437 result->size = attrib_info->size;
9438 result->type = attrib_info->type;
9439 Bucket* bucket = CreateBucket(name_bucket_id);
9440 bucket->SetFromString(attrib_info->name.c_str());
9441 return error::kNoError;
9444 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
9445 const void* cmd_data) {
9446 #if 1 // No binary shader support.
9447 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9448 return error::kNoError;
9450 GLsizei n = static_cast<GLsizei>(c.n);
9452 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9453 return error::kNoError;
9455 GLsizei length = static_cast<GLsizei>(c.length);
9457 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9458 return error::kNoError;
9461 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9462 return error::kOutOfBounds;
9464 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9465 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9466 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9467 const void* binary = GetSharedMemoryAs<const void*>(
9468 c.binary_shm_id, c.binary_shm_offset, length);
9469 if (shaders == NULL || binary == NULL) {
9470 return error::kOutOfBounds;
9472 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9473 for (GLsizei ii = 0; ii < n; ++ii) {
9474 Shader* shader = GetShader(shaders[ii]);
9476 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9477 return error::kNoError;
9479 service_ids[ii] = shader->service_id();
9481 // TODO(gman): call glShaderBinary
9482 return error::kNoError;
9486 void GLES2DecoderImpl::DoSwapBuffers() {
9487 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9489 int this_frame_number = frame_number_++;
9490 // TRACE_EVENT for gpu tests:
9491 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9492 TRACE_EVENT_SCOPE_THREAD,
9493 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9494 "width", (is_offscreen ? offscreen_size_.width() :
9495 surface_->GetSize().width()));
9496 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9497 "offscreen", is_offscreen,
9498 "frame", this_frame_number);
9500 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9504 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9507 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9508 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9509 is_offscreen ? offscreen_size_ : surface_->GetSize());
9512 // If offscreen then don't actually SwapBuffers to the display. Just copy
9513 // the rendered frame to another frame buffer.
9515 TRACE_EVENT2("gpu", "Offscreen",
9516 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9517 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9518 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9519 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9521 if (workarounds().needs_offscreen_buffer_workaround) {
9522 offscreen_saved_frame_buffer_->Create();
9526 // Allocate the offscreen saved color texture.
9527 DCHECK(offscreen_saved_color_format_);
9528 offscreen_saved_color_texture_->AllocateStorage(
9529 offscreen_size_, offscreen_saved_color_format_, false);
9531 offscreen_saved_frame_buffer_->AttachRenderTexture(
9532 offscreen_saved_color_texture_.get());
9533 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9534 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9535 GL_FRAMEBUFFER_COMPLETE) {
9536 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9537 << "because offscreen saved FBO was incomplete.";
9538 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9542 // Clear the offscreen color texture.
9543 // TODO(piman): Is this still necessary?
9545 ScopedFrameBufferBinder binder(this,
9546 offscreen_saved_frame_buffer_->id());
9547 glClearColor(0, 0, 0, 0);
9548 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9549 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9550 glClear(GL_COLOR_BUFFER_BIT);
9551 RestoreClearState();
9555 UpdateParentTextureInfo();
9558 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9560 ScopedGLErrorSuppressor suppressor(
9561 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9563 if (IsOffscreenBufferMultisampled()) {
9564 // For multisampled buffers, resolve the frame buffer.
9565 ScopedResolvedFrameBufferBinder binder(this, true, false);
9567 ScopedFrameBufferBinder binder(this,
9568 offscreen_target_frame_buffer_->id());
9570 if (offscreen_target_buffer_preserved_) {
9571 // Copy the target frame buffer to the saved offscreen texture.
9572 offscreen_saved_color_texture_->Copy(
9573 offscreen_saved_color_texture_->size(),
9574 offscreen_saved_color_format_);
9576 // Flip the textures in the parent context via the texture manager.
9577 if (!!offscreen_saved_color_texture_info_.get())
9578 offscreen_saved_color_texture_info_->texture()->
9579 SetServiceId(offscreen_target_color_texture_->id());
9581 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9582 offscreen_target_frame_buffer_->AttachRenderTexture(
9583 offscreen_target_color_texture_.get());
9586 // Ensure the side effects of the copy are visible to the parent
9587 // context. There is no need to do this for ANGLE because it uses a
9588 // single D3D device for all contexts.
9589 if (!feature_info_->feature_flags().is_angle)
9593 if (!surface_->SwapBuffers()) {
9594 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9595 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9599 // This may be a slow command. Exit command processing to allow for
9600 // context preemption and GPU watchdog checks.
9601 ExitCommandProcessingEarly();
9604 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9605 uint32 immediate_data_size,
9606 const void* cmd_data) {
9607 const gles2::cmds::EnableFeatureCHROMIUM& c =
9608 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
9609 Bucket* bucket = GetBucket(c.bucket_id);
9610 if (!bucket || bucket->size() == 0) {
9611 return error::kInvalidArguments;
9613 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9614 Result* result = GetSharedMemoryAs<Result*>(
9615 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9617 return error::kOutOfBounds;
9619 // Check that the client initialized the result.
9621 return error::kInvalidArguments;
9623 std::string feature_str;
9624 if (!bucket->GetAsString(&feature_str)) {
9625 return error::kInvalidArguments;
9628 // TODO(gman): make this some kind of table to function pointer thingy.
9629 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9630 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9631 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9632 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9633 // TODO(gman): decide how to remove the need for this const_cast.
9634 // I could make validators_ non const but that seems bad as this is the only
9635 // place it is needed. I could make some special friend class of validators
9636 // just to allow this to set them. That seems silly. I could refactor this
9637 // code to use the extension mechanism or the initialization attributes to
9638 // turn this feature on. Given that the only real point of this is to make
9639 // the conformance tests pass and given that there is lots of real work that
9640 // needs to be done it seems like refactoring for one to one of those
9641 // methods is a very low priority.
9642 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9643 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9644 force_webgl_glsl_validation_ = true;
9645 InitializeShaderTranslator();
9647 return error::kNoError;
9650 *result = 1; // true.
9651 return error::kNoError;
9654 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9655 uint32 immediate_data_size,
9656 const void* cmd_data) {
9657 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
9658 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
9660 Bucket* bucket = CreateBucket(c.bucket_id);
9661 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9662 info->Initialize(disallowed_features_);
9663 bucket->SetFromString(info->extensions().c_str());
9664 return error::kNoError;
9667 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9668 uint32 immediate_data_size,
9669 const void* cmd_data) {
9670 const gles2::cmds::RequestExtensionCHROMIUM& c =
9671 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
9672 Bucket* bucket = GetBucket(c.bucket_id);
9673 if (!bucket || bucket->size() == 0) {
9674 return error::kInvalidArguments;
9676 std::string feature_str;
9677 if (!bucket->GetAsString(&feature_str)) {
9678 return error::kInvalidArguments;
9681 bool desire_webgl_glsl_validation =
9682 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9683 bool desire_standard_derivatives = false;
9684 bool desire_frag_depth = false;
9685 bool desire_draw_buffers = false;
9686 bool desire_shader_texture_lod = false;
9687 if (force_webgl_glsl_validation_) {
9688 desire_standard_derivatives =
9689 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9691 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9692 desire_draw_buffers =
9693 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9694 desire_shader_texture_lod =
9695 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9698 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9699 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9700 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9701 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9702 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9703 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9704 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9705 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9706 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
9707 InitializeShaderTranslator();
9710 UpdateCapabilities();
9712 return error::kNoError;
9715 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9716 uint32 immediate_data_size,
9717 const void* cmd_data) {
9718 const gles2::cmds::GetMultipleIntegervCHROMIUM& c =
9719 *static_cast<const gles2::cmds::GetMultipleIntegervCHROMIUM*>(cmd_data);
9720 GLuint count = c.count;
9722 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9723 return error::kOutOfBounds;
9725 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9726 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9727 if (pnames == NULL) {
9728 return error::kOutOfBounds;
9731 // We have to copy them since we use them twice so the client
9732 // can't change them between the time we validate them and the time we use
9734 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9735 memcpy(enums.get(), pnames, pnames_size);
9737 // Count up the space needed for the result.
9738 uint32 num_results = 0;
9739 for (GLuint ii = 0; ii < count; ++ii) {
9740 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9742 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9743 "glGetMultipleCHROMIUM", enums[ii], "pname");
9744 return error::kNoError;
9746 // Num will never be more than 4.
9748 if (!SafeAddUint32(num_results, num, &num_results)) {
9749 return error::kOutOfBounds;
9753 uint32 result_size = 0;
9754 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9755 return error::kOutOfBounds;
9758 if (result_size != static_cast<uint32>(c.size)) {
9761 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9762 return error::kNoError;
9765 GLint* results = GetSharedMemoryAs<GLint*>(
9766 c.results_shm_id, c.results_shm_offset, result_size);
9767 if (results == NULL) {
9768 return error::kOutOfBounds;
9771 // Check the results have been cleared in case the context was lost.
9772 for (uint32 ii = 0; ii < num_results; ++ii) {
9774 return error::kInvalidArguments;
9779 GLint* start = results;
9780 for (GLuint ii = 0; ii < count; ++ii) {
9781 GLsizei num_written = 0;
9782 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9783 !GetHelper(enums[ii], results, &num_written)) {
9784 DoGetIntegerv(enums[ii], results);
9786 results += num_written;
9789 // Just to verify. Should this be a DCHECK?
9790 if (static_cast<uint32>(results - start) != num_results) {
9791 return error::kOutOfBounds;
9794 return error::kNoError;
9797 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9798 uint32 immediate_data_size,
9799 const void* cmd_data) {
9800 const gles2::cmds::GetProgramInfoCHROMIUM& c =
9801 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
9802 GLuint program_id = static_cast<GLuint>(c.program);
9803 uint32 bucket_id = c.bucket_id;
9804 Bucket* bucket = CreateBucket(bucket_id);
9805 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9806 Program* program = NULL;
9807 program = GetProgram(program_id);
9808 if (!program || !program->IsValid()) {
9809 return error::kNoError;
9811 program->GetProgramInfo(program_manager(), bucket);
9812 return error::kNoError;
9815 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9816 switch (reset_status_) {
9818 // TODO(kbr): improve the precision of the error code in this case.
9819 // Consider delegating to context for error code if MakeCurrent fails.
9820 return error::kUnknown;
9821 case GL_GUILTY_CONTEXT_RESET_ARB:
9822 return error::kGuilty;
9823 case GL_INNOCENT_CONTEXT_RESET_ARB:
9824 return error::kInnocent;
9825 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9826 return error::kUnknown;
9830 return error::kUnknown;
9833 void GLES2DecoderImpl::MaybeExitOnContextLost() {
9834 // Some D3D drivers cannot recover from device lost in the GPU process
9835 // sandbox. Allow a new GPU process to launch.
9836 if (workarounds().exit_on_context_lost) {
9837 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
9838 << " a D3D device in the Chrome GPU process sandbox.";
9840 base::win::SetShouldCrashOnProcessDetach(false);
9846 bool GLES2DecoderImpl::WasContextLost() {
9847 if (reset_status_ != GL_NO_ERROR) {
9848 MaybeExitOnContextLost();
9851 if (context_->WasAllocatedUsingRobustnessExtension()) {
9852 GLenum status = GL_NO_ERROR;
9853 if (has_robustness_extension_)
9854 status = glGetGraphicsResetStatusARB();
9855 if (status != GL_NO_ERROR) {
9856 // The graphics card was reset. Signal a lost context to the application.
9857 reset_status_ = status;
9858 reset_by_robustness_extension_ = true;
9859 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9860 << " context lost via ARB/EXT_robustness. Reset status = "
9861 << GLES2Util::GetStringEnum(status);
9862 MaybeExitOnContextLost();
9869 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9870 return WasContextLost() && reset_by_robustness_extension_;
9873 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9874 // Only loses the context once.
9875 if (reset_status_ != GL_NO_ERROR) {
9879 if (workarounds().use_virtualized_gl_contexts) {
9880 // If the context is virtual, the real context being guilty does not ensure
9881 // that the virtual context is guilty.
9882 if (reset_status == GL_GUILTY_CONTEXT_RESET_ARB) {
9883 reset_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
9885 } else if (reset_status == GL_UNKNOWN_CONTEXT_RESET_ARB &&
9886 has_robustness_extension_) {
9887 // If the reason for the call was a GL error, we can try to determine the
9888 // reset status more accurately.
9889 GLenum driver_status = glGetGraphicsResetStatusARB();
9890 if (driver_status == GL_GUILTY_CONTEXT_RESET_ARB ||
9891 driver_status == GL_INNOCENT_CONTEXT_RESET_ARB) {
9892 reset_status = driver_status;
9896 // Marks this context as lost.
9897 reset_status_ = reset_status;
9898 current_decoder_error_ = error::kLostContext;
9901 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9902 uint32 immediate_data_size,
9903 const void* cmd_data) {
9904 return error::kUnknownCommand;
9907 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9908 uint32 immediate_data_size,
9909 const void* cmd_data) {
9910 const gles2::cmds::WaitSyncPointCHROMIUM& c =
9911 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
9912 uint32 sync_point = c.sync_point;
9913 if (wait_sync_point_callback_.is_null())
9914 return error::kNoError;
9916 return wait_sync_point_callback_.Run(sync_point) ?
9917 error::kNoError : error::kDeferCommandUntilLater;
9920 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9921 uint32 immediate_data_size,
9922 const void* cmd_data) {
9923 if (surface_->DeferDraws())
9924 return error::kDeferCommandUntilLater;
9925 if (!surface_->SetBackbufferAllocation(false))
9926 return error::kLostContext;
9927 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9928 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9929 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9930 return error::kNoError;
9933 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9934 GLsizei n, const GLuint* client_ids) {
9935 for (GLsizei ii = 0; ii < n; ++ii) {
9936 if (query_manager_->GetQuery(client_ids[ii])) {
9940 query_manager_->GenQueries(n, client_ids);
9944 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9945 GLsizei n, const GLuint* client_ids) {
9946 for (GLsizei ii = 0; ii < n; ++ii) {
9947 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9948 if (query && !query->IsDeleted()) {
9949 ContextState::QueryMap::iterator it =
9950 state_.current_queries.find(query->target());
9951 if (it != state_.current_queries.end())
9952 state_.current_queries.erase(it);
9954 query->Destroy(true);
9956 query_manager_->RemoveQuery(client_ids[ii]);
9960 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
9961 if (query_manager_.get() == NULL) {
9964 if (!query_manager_->ProcessPendingQueries(did_finish)) {
9965 current_decoder_error_ = error::kOutOfBounds;
9967 return query_manager_->HavePendingQueries();
9970 // Note that if there are no pending readpixels right now,
9971 // this function will call the callback immediately.
9972 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9973 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9974 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9980 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9981 while (!pending_readpixel_fences_.empty() &&
9982 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9983 std::vector<base::Closure> callbacks =
9984 pending_readpixel_fences_.front()->callbacks;
9985 pending_readpixel_fences_.pop();
9986 for (size_t i = 0; i < callbacks.size(); i++) {
9992 bool GLES2DecoderImpl::HasMoreIdleWork() {
9993 return !pending_readpixel_fences_.empty() ||
9994 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9997 void GLES2DecoderImpl::PerformIdleWork() {
9998 ProcessPendingReadPixels();
9999 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
10001 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
10002 ProcessFinishedAsyncTransfers();
10005 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
10006 const void* cmd_data) {
10007 const gles2::cmds::BeginQueryEXT& c =
10008 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
10009 GLenum target = static_cast<GLenum>(c.target);
10010 GLuint client_id = static_cast<GLuint>(c.id);
10011 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
10012 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10015 case GL_COMMANDS_ISSUED_CHROMIUM:
10016 case GL_LATENCY_QUERY_CHROMIUM:
10017 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
10018 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
10019 case GL_GET_ERROR_QUERY_CHROMIUM:
10021 case GL_COMMANDS_COMPLETED_CHROMIUM:
10022 if (!features().chromium_sync_query) {
10023 LOCAL_SET_GL_ERROR(
10024 GL_INVALID_OPERATION, "glBeginQueryEXT",
10025 "not enabled for commands completed queries");
10026 return error::kNoError;
10030 if (!features().occlusion_query_boolean) {
10031 LOCAL_SET_GL_ERROR(
10032 GL_INVALID_OPERATION, "glBeginQueryEXT",
10033 "not enabled for occlusion queries");
10034 return error::kNoError;
10039 if (state_.current_queries.find(target) != state_.current_queries.end()) {
10040 LOCAL_SET_GL_ERROR(
10041 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
10042 return error::kNoError;
10045 if (client_id == 0) {
10046 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
10047 return error::kNoError;
10050 QueryManager::Query* query = query_manager_->GetQuery(client_id);
10052 if (!query_manager_->IsValidQuery(client_id)) {
10053 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10055 "id not made by glGenQueriesEXT");
10056 return error::kNoError;
10058 query = query_manager_->CreateQuery(
10059 target, client_id, sync_shm_id, sync_shm_offset);
10062 if (query->target() != target) {
10063 LOCAL_SET_GL_ERROR(
10064 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
10065 return error::kNoError;
10066 } else if (query->shm_id() != sync_shm_id ||
10067 query->shm_offset() != sync_shm_offset) {
10068 DLOG(ERROR) << "Shared memory used by query not the same as before";
10069 return error::kInvalidArguments;
10072 if (!query_manager_->BeginQuery(query)) {
10073 return error::kOutOfBounds;
10076 state_.current_queries[target] = query;
10077 return error::kNoError;
10080 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
10081 const void* cmd_data) {
10082 const gles2::cmds::EndQueryEXT& c =
10083 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
10084 GLenum target = static_cast<GLenum>(c.target);
10085 uint32 submit_count = static_cast<GLuint>(c.submit_count);
10086 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
10088 if (it == state_.current_queries.end()) {
10089 LOCAL_SET_GL_ERROR(
10090 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
10091 return error::kNoError;
10094 QueryManager::Query* query = it->second.get();
10095 if (!query_manager_->EndQuery(query, submit_count)) {
10096 return error::kOutOfBounds;
10099 query_manager_->ProcessPendingTransferQueries();
10101 state_.current_queries.erase(it);
10102 return error::kNoError;
10105 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
10106 GLsizei n, const GLuint* client_ids) {
10107 for (GLsizei ii = 0; ii < n; ++ii) {
10108 if (GetVertexAttribManager(client_ids[ii])) {
10113 if (!features().native_vertex_array_object) {
10115 for (GLsizei ii = 0; ii < n; ++ii) {
10116 CreateVertexAttribManager(client_ids[ii], 0, true);
10119 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10121 glGenVertexArraysOES(n, service_ids.get());
10122 for (GLsizei ii = 0; ii < n; ++ii) {
10123 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
10130 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10131 GLsizei n, const GLuint* client_ids) {
10132 for (GLsizei ii = 0; ii < n; ++ii) {
10133 VertexAttribManager* vao =
10134 GetVertexAttribManager(client_ids[ii]);
10135 if (vao && !vao->IsDeleted()) {
10136 if (state_.vertex_attrib_manager.get() == vao) {
10137 DoBindVertexArrayOES(0);
10139 RemoveVertexAttribManager(client_ids[ii]);
10144 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
10145 VertexAttribManager* vao = NULL;
10146 if (client_id != 0) {
10147 vao = GetVertexAttribManager(client_id);
10149 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10150 // only allows names that have been previously generated. As such, we do
10151 // not generate new names here.
10152 LOCAL_SET_GL_ERROR(
10153 GL_INVALID_OPERATION,
10154 "glBindVertexArrayOES", "bad vertex array id.");
10155 current_decoder_error_ = error::kNoError;
10159 vao = state_.default_vertex_attrib_manager.get();
10162 // Only set the VAO state if it's changed
10163 if (state_.vertex_attrib_manager.get() != vao) {
10164 state_.vertex_attrib_manager = vao;
10165 if (!features().native_vertex_array_object) {
10166 EmulateVertexArrayState();
10168 GLuint service_id = vao->service_id();
10169 glBindVertexArrayOES(service_id);
10174 // Used when OES_vertex_array_object isn't natively supported
10175 void GLES2DecoderImpl::EmulateVertexArrayState() {
10176 // Setup the Vertex attribute state
10177 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
10178 RestoreStateForAttrib(vv, true);
10181 // Setup the element buffer
10182 Buffer* element_array_buffer =
10183 state_.vertex_attrib_manager->element_array_buffer();
10184 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
10185 element_array_buffer ? element_array_buffer->service_id() : 0);
10188 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
10189 const VertexAttribManager* vao =
10190 GetVertexAttribManager(client_id);
10191 return vao && vao->IsValid() && !vao->IsDeleted();
10194 #if defined(OS_MACOSX)
10195 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
10196 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
10198 if (it != texture_to_io_surface_map_.end()) {
10199 // Found a previous IOSurface bound to this texture; release it.
10200 IOSurfaceRef surface = it->second;
10201 CFRelease(surface);
10202 texture_to_io_surface_map_.erase(it);
10207 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10208 GLenum target, GLsizei width, GLsizei height,
10209 GLuint io_surface_id, GLuint plane) {
10210 #if defined(OS_MACOSX)
10211 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
10212 LOCAL_SET_GL_ERROR(
10213 GL_INVALID_OPERATION,
10214 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10218 if (target != GL_TEXTURE_RECTANGLE_ARB) {
10219 // This might be supported in the future, and if we could require
10220 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10221 // could delete a lot of code. For now, perform strict validation so we
10222 // know what's going on.
10223 LOCAL_SET_GL_ERROR(
10224 GL_INVALID_OPERATION,
10225 "glTexImageIOSurface2DCHROMIUM",
10226 "requires TEXTURE_RECTANGLE_ARB target");
10230 // Default target might be conceptually valid, but disallow it to avoid
10232 TextureRef* texture_ref =
10233 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10234 if (!texture_ref) {
10235 LOCAL_SET_GL_ERROR(
10236 GL_INVALID_OPERATION,
10237 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10241 // Look up the new IOSurface. Note that because of asynchrony
10242 // between processes this might fail; during live resizing the
10243 // plugin process might allocate and release an IOSurface before
10244 // this process gets a chance to look it up. Hold on to any old
10245 // IOSurface in this case.
10246 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
10248 LOCAL_SET_GL_ERROR(
10249 GL_INVALID_OPERATION,
10250 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
10254 // Release any IOSurface previously bound to this texture.
10255 ReleaseIOSurfaceForTexture(texture_ref->service_id());
10257 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
10258 texture_to_io_surface_map_.insert(
10259 std::make_pair(texture_ref->service_id(), surface));
10261 CGLContextObj context =
10262 static_cast<CGLContextObj>(context_->GetHandle());
10264 CGLError err = CGLTexImageIOSurface2D(
10271 GL_UNSIGNED_INT_8_8_8_8_REV,
10275 if (err != kCGLNoError) {
10276 LOCAL_SET_GL_ERROR(
10277 GL_INVALID_OPERATION,
10278 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
10282 texture_manager()->SetLevelInfo(
10283 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
10284 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
10287 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10288 "glTexImageIOSurface2DCHROMIUM", "not supported.");
10292 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
10293 switch (internalformat) {
10304 case GL_LUMINANCE8_ALPHA8_EXT:
10305 return GL_LUMINANCE_ALPHA;
10306 case GL_LUMINANCE8_EXT:
10307 return GL_LUMINANCE;
10308 case GL_ALPHA8_EXT:
10310 case GL_RGBA32F_EXT:
10312 case GL_RGB32F_EXT:
10314 case GL_ALPHA32F_EXT:
10316 case GL_LUMINANCE32F_EXT:
10317 return GL_LUMINANCE;
10318 case GL_LUMINANCE_ALPHA32F_EXT:
10319 return GL_LUMINANCE_ALPHA;
10320 case GL_RGBA16F_EXT:
10322 case GL_RGB16F_EXT:
10324 case GL_ALPHA16F_EXT:
10326 case GL_LUMINANCE16F_EXT:
10327 return GL_LUMINANCE;
10328 case GL_LUMINANCE_ALPHA16F_EXT:
10329 return GL_LUMINANCE_ALPHA;
10331 return GL_BGRA_EXT;
10332 case GL_SRGB8_ALPHA8_EXT:
10333 return GL_SRGB_ALPHA_EXT;
10339 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
10340 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
10341 GLenum internal_format, GLenum dest_type) {
10342 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
10344 TextureRef* dest_texture_ref = GetTexture(dest_id);
10345 TextureRef* source_texture_ref = GetTexture(source_id);
10347 if (!source_texture_ref || !dest_texture_ref) {
10348 LOCAL_SET_GL_ERROR(
10349 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
10353 if (GL_TEXTURE_2D != target) {
10354 LOCAL_SET_GL_ERROR(
10355 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
10359 Texture* source_texture = source_texture_ref->texture();
10360 Texture* dest_texture = dest_texture_ref->texture();
10361 if (dest_texture->target() != GL_TEXTURE_2D ||
10362 (source_texture->target() != GL_TEXTURE_2D &&
10363 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
10364 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
10365 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10366 "glCopyTextureCHROMIUM",
10367 "invalid texture target binding");
10371 int source_width, source_height, dest_width, dest_height;
10373 gfx::GLImage* image =
10374 source_texture->GetLevelImage(source_texture->target(), 0);
10376 gfx::Size size = image->GetSize();
10377 source_width = size.width();
10378 source_height = size.height();
10379 if (source_width <= 0 || source_height <= 0) {
10380 LOCAL_SET_GL_ERROR(
10382 "glCopyTextureChromium", "invalid image size");
10386 if (!source_texture->GetLevelSize(
10387 source_texture->target(), 0, &source_width, &source_height)) {
10388 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10389 "glCopyTextureChromium",
10390 "source texture has no level 0");
10394 // Check that this type of texture is allowed.
10395 if (!texture_manager()->ValidForTarget(
10396 source_texture->target(), level, source_width, source_height, 1)) {
10397 LOCAL_SET_GL_ERROR(
10398 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
10403 // Clear the source texture if necessary.
10404 if (!texture_manager()->ClearTextureLevel(
10405 this, source_texture_ref, source_texture->target(), 0)) {
10406 LOCAL_SET_GL_ERROR(
10407 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
10411 GLenum source_type = 0;
10412 GLenum source_internal_format = 0;
10413 source_texture->GetLevelType(
10414 source_texture->target(), 0, &source_type, &source_internal_format);
10416 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
10417 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
10418 // renderable on some platforms.
10419 bool valid_dest_format = internal_format == GL_RGB ||
10420 internal_format == GL_RGBA ||
10421 internal_format == GL_BGRA_EXT;
10422 bool valid_source_format = source_internal_format == GL_ALPHA ||
10423 source_internal_format == GL_RGB ||
10424 source_internal_format == GL_RGBA ||
10425 source_internal_format == GL_LUMINANCE ||
10426 source_internal_format == GL_LUMINANCE_ALPHA ||
10427 source_internal_format == GL_BGRA_EXT;
10428 if (!valid_source_format || !valid_dest_format) {
10429 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10430 "glCopyTextureCHROMIUM",
10431 "invalid internal format");
10435 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10436 // needed because it takes 10s of milliseconds to initialize.
10437 if (!copy_texture_CHROMIUM_.get()) {
10438 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10439 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
10440 copy_texture_CHROMIUM_->Initialize(this);
10441 RestoreCurrentFramebufferBindings();
10442 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
10446 GLenum dest_type_previous = dest_type;
10447 GLenum dest_internal_format = internal_format;
10448 bool dest_level_defined = dest_texture->GetLevelSize(
10449 GL_TEXTURE_2D, level, &dest_width, &dest_height);
10451 if (dest_level_defined) {
10452 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
10453 &dest_internal_format);
10456 // Resize the destination texture to the dimensions of the source texture.
10457 if (!dest_level_defined || dest_width != source_width ||
10458 dest_height != source_height ||
10459 dest_internal_format != internal_format ||
10460 dest_type_previous != dest_type) {
10461 // Ensure that the glTexImage2D succeeds.
10462 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10463 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10465 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
10466 0, internal_format, dest_type, NULL);
10467 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10468 if (error != GL_NO_ERROR) {
10469 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
10473 texture_manager()->SetLevelInfo(
10474 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
10475 source_height, 1, 0, internal_format, dest_type, true);
10477 texture_manager()->SetLevelCleared(
10478 dest_texture_ref, GL_TEXTURE_2D, level, true);
10481 ScopedModifyPixels modify(dest_texture_ref);
10483 // Try using GLImage::CopyTexImage when possible.
10484 bool unpack_premultiply_alpha_change =
10485 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
10486 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change && !level) {
10487 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10488 if (image->CopyTexImage(GL_TEXTURE_2D))
10492 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
10494 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10495 // before presenting.
10496 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
10497 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10498 // instead of using default matrix crbug.com/226218.
10499 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
10500 0.0f, 1.0f, 0.0f, 0.0f,
10501 0.0f, 0.0f, 1.0f, 0.0f,
10502 0.0f, 0.0f, 0.0f, 1.0f};
10503 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
10505 source_texture->target(),
10506 source_texture->service_id(),
10507 dest_texture->service_id(),
10512 unpack_premultiply_alpha_,
10513 unpack_unpremultiply_alpha_,
10516 copy_texture_CHROMIUM_->DoCopyTexture(this,
10517 source_texture->target(),
10518 source_texture->service_id(),
10519 source_internal_format,
10520 dest_texture->service_id(),
10526 unpack_premultiply_alpha_,
10527 unpack_unpremultiply_alpha_);
10530 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10533 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10534 switch (internalformat) {
10536 return GL_UNSIGNED_SHORT_5_6_5;
10538 return GL_UNSIGNED_SHORT_4_4_4_4;
10540 return GL_UNSIGNED_SHORT_5_5_5_1;
10542 return GL_UNSIGNED_BYTE;
10544 return GL_UNSIGNED_BYTE;
10545 case GL_LUMINANCE8_ALPHA8_EXT:
10546 return GL_UNSIGNED_BYTE;
10547 case GL_LUMINANCE8_EXT:
10548 return GL_UNSIGNED_BYTE;
10549 case GL_ALPHA8_EXT:
10550 return GL_UNSIGNED_BYTE;
10551 case GL_RGBA32F_EXT:
10553 case GL_RGB32F_EXT:
10555 case GL_ALPHA32F_EXT:
10557 case GL_LUMINANCE32F_EXT:
10559 case GL_LUMINANCE_ALPHA32F_EXT:
10561 case GL_RGBA16F_EXT:
10562 return GL_HALF_FLOAT_OES;
10563 case GL_RGB16F_EXT:
10564 return GL_HALF_FLOAT_OES;
10565 case GL_ALPHA16F_EXT:
10566 return GL_HALF_FLOAT_OES;
10567 case GL_LUMINANCE16F_EXT:
10568 return GL_HALF_FLOAT_OES;
10569 case GL_LUMINANCE_ALPHA16F_EXT:
10570 return GL_HALF_FLOAT_OES;
10572 return GL_UNSIGNED_BYTE;
10578 void GLES2DecoderImpl::DoTexStorage2DEXT(
10581 GLenum internal_format,
10584 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10585 "width", width, "height", height);
10586 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10587 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10588 LOCAL_SET_GL_ERROR(
10589 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10592 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10594 if (!texture_ref) {
10595 LOCAL_SET_GL_ERROR(
10596 GL_INVALID_OPERATION,
10597 "glTexStorage2DEXT", "unknown texture for target");
10600 Texture* texture = texture_ref->texture();
10601 if (texture->IsAttachedToFramebuffer()) {
10602 framebuffer_state_.clear_state_dirty = true;
10604 if (texture->IsImmutable()) {
10605 LOCAL_SET_GL_ERROR(
10606 GL_INVALID_OPERATION,
10607 "glTexStorage2DEXT", "texture is immutable");
10611 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10612 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10615 GLsizei level_width = width;
10616 GLsizei level_height = height;
10617 uint32 estimated_size = 0;
10618 for (int ii = 0; ii < levels; ++ii) {
10619 uint32 level_size = 0;
10620 if (!GLES2Util::ComputeImageDataSizes(
10621 level_width, level_height, format, type, state_.unpack_alignment,
10622 &estimated_size, NULL, NULL) ||
10623 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10624 LOCAL_SET_GL_ERROR(
10625 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10628 level_width = std::max(1, level_width >> 1);
10629 level_height = std::max(1, level_height >> 1);
10631 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10632 LOCAL_SET_GL_ERROR(
10633 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10638 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10639 glTexStorage2DEXT(target, levels, internal_format, width, height);
10640 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10641 if (error == GL_NO_ERROR) {
10642 GLsizei level_width = width;
10643 GLsizei level_height = height;
10644 for (int ii = 0; ii < levels; ++ii) {
10645 texture_manager()->SetLevelInfo(
10646 texture_ref, target, ii, format,
10647 level_width, level_height, 1, 0, format, type, false);
10648 level_width = std::max(1, level_width >> 1);
10649 level_height = std::max(1, level_height >> 1);
10651 texture->SetImmutable(true);
10655 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10656 uint32 immediate_data_size,
10657 const void* cmd_data) {
10658 return error::kUnknownCommand;
10661 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10662 const GLbyte* data) {
10663 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10664 "context", logger_.GetLogPrefix(),
10665 "mailbox[0]", static_cast<unsigned char>(data[0]));
10667 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10669 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
10672 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
10673 GLenum target, const GLbyte* data) {
10674 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10675 "context", logger_.GetLogPrefix(),
10676 "mailbox[0]", static_cast<unsigned char>(data[0]));
10678 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
10682 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
10683 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
10684 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10685 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
10686 "mailbox that was not generated by "
10687 "GenMailboxCHROMIUM.";
10689 if (!texture_ref) {
10690 LOCAL_SET_GL_ERROR(
10691 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
10695 Texture* produced = texture_manager()->Produce(texture_ref);
10697 LOCAL_SET_GL_ERROR(
10698 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
10702 if (produced->target() != target) {
10703 LOCAL_SET_GL_ERROR(
10704 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
10708 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
10711 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10712 const GLbyte* data) {
10713 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10714 "context", logger_.GetLogPrefix(),
10715 "mailbox[0]", static_cast<unsigned char>(data[0]));
10716 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10717 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10718 "mailbox that was not generated by "
10719 "GenMailboxCHROMIUM.";
10721 scoped_refptr<TextureRef> texture_ref =
10722 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10723 if (!texture_ref.get()) {
10724 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10725 "glConsumeTextureCHROMIUM",
10726 "unknown texture for target");
10729 GLuint client_id = texture_ref->client_id();
10731 LOCAL_SET_GL_ERROR(
10732 GL_INVALID_OPERATION,
10733 "glConsumeTextureCHROMIUM", "unknown texture for target");
10736 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
10738 LOCAL_SET_GL_ERROR(
10739 GL_INVALID_OPERATION,
10740 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10743 if (texture->target() != target) {
10744 LOCAL_SET_GL_ERROR(
10745 GL_INVALID_OPERATION,
10746 "glConsumeTextureCHROMIUM", "invalid target");
10750 DeleteTexturesHelper(1, &client_id);
10751 texture_ref = texture_manager()->Consume(client_id, texture);
10752 glBindTexture(target, texture_ref->service_id());
10754 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10755 unit.bind_target = target;
10757 case GL_TEXTURE_2D:
10758 unit.bound_texture_2d = texture_ref;
10760 case GL_TEXTURE_CUBE_MAP:
10761 unit.bound_texture_cube_map = texture_ref;
10763 case GL_TEXTURE_EXTERNAL_OES:
10764 unit.bound_texture_external_oes = texture_ref;
10766 case GL_TEXTURE_RECTANGLE_ARB:
10767 unit.bound_texture_rectangle_arb = texture_ref;
10770 NOTREACHED(); // Validation should prevent us getting here.
10775 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10776 uint32_t immediate_data_size,
10777 const void* cmd_data) {
10778 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
10780 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
10782 GLenum target = static_cast<GLenum>(c.target);
10783 uint32_t data_size;
10784 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
10785 return error::kOutOfBounds;
10787 if (data_size > immediate_data_size) {
10788 return error::kOutOfBounds;
10790 const GLbyte* mailbox =
10791 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
10792 if (!validators_->texture_bind_target.IsValid(target)) {
10793 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10794 "glCreateAndConsumeTextureCHROMIUM", target, "target");
10795 return error::kNoError;
10797 if (mailbox == NULL) {
10798 return error::kOutOfBounds;
10800 uint32_t client_id = c.client_id;
10801 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
10802 return error::kNoError;
10805 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
10806 const GLbyte* data, GLuint client_id) {
10807 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10808 "context", logger_.GetLogPrefix(),
10809 "mailbox[0]", static_cast<unsigned char>(data[0]));
10810 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10811 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10812 "passed a mailbox that was not "
10813 "generated by GenMailboxCHROMIUM.";
10815 TextureRef* texture_ref = GetTexture(client_id);
10817 LOCAL_SET_GL_ERROR(
10818 GL_INVALID_OPERATION,
10819 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10822 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
10824 LOCAL_SET_GL_ERROR(
10825 GL_INVALID_OPERATION,
10826 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10829 if (texture->target() != target) {
10830 LOCAL_SET_GL_ERROR(
10831 GL_INVALID_OPERATION,
10832 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10836 texture_ref = texture_manager()->Consume(client_id, texture);
10839 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
10840 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
10841 return valuebuffer && valuebuffer->IsValid();
10844 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
10845 GLuint client_id) {
10846 Valuebuffer* valuebuffer = NULL;
10847 if (client_id != 0) {
10848 valuebuffer = GetValuebuffer(client_id);
10849 if (!valuebuffer) {
10850 if (!group_->bind_generates_resource()) {
10851 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
10852 "id not generated by glBindValuebufferCHROMIUM");
10856 // It's a new id so make a valuebuffer for it.
10857 CreateValuebuffer(client_id);
10858 valuebuffer = GetValuebuffer(client_id);
10860 valuebuffer->MarkAsValid();
10862 state_.bound_valuebuffer = valuebuffer;
10865 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
10866 GLenum subscription) {
10867 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
10870 state_.bound_valuebuffer.get()->AddSubscription(subscription);
10873 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
10874 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
10877 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
10880 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
10882 GLenum subscription) {
10883 if (!CheckCurrentValuebufferForSubscription(
10884 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
10887 if (!CheckSubscriptionTarget(location, subscription,
10888 "glPopulateSubscribedValuesCHROMIUM")) {
10891 const ValueState* state =
10892 state_.bound_valuebuffer.get()->GetState(subscription);
10894 switch (subscription) {
10895 case GL_MOUSE_POSITION_CHROMIUM:
10896 DoUniform2iv(location, 1, state->int_value);
10899 NOTREACHED() << "Unhandled uniform subscription target "
10906 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10907 GLsizei length, const GLchar* marker) {
10911 debug_marker_manager_.SetMarker(
10912 length ? std::string(marker, length) : std::string(marker));
10915 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10916 GLsizei length, const GLchar* marker) {
10920 std::string name = length ? std::string(marker, length) : std::string(marker);
10921 debug_marker_manager_.PushGroup(name);
10922 gpu_tracer_->Begin(name, kTraceGroupMarker);
10925 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10926 debug_marker_manager_.PopGroup();
10927 gpu_tracer_->End(kTraceGroupMarker);
10930 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10931 GLenum target, GLint image_id) {
10932 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10934 if (target == GL_TEXTURE_CUBE_MAP) {
10935 LOCAL_SET_GL_ERROR(
10937 "glBindTexImage2DCHROMIUM", "invalid target");
10941 // Default target might be conceptually valid, but disallow it to avoid
10943 TextureRef* texture_ref =
10944 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10945 if (!texture_ref) {
10946 LOCAL_SET_GL_ERROR(
10947 GL_INVALID_OPERATION,
10948 "glBindTexImage2DCHROMIUM", "no texture bound");
10952 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10954 LOCAL_SET_GL_ERROR(
10955 GL_INVALID_OPERATION,
10956 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10961 ScopedGLErrorSuppressor suppressor(
10962 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10963 if (!gl_image->BindTexImage(target)) {
10964 LOCAL_SET_GL_ERROR(
10965 GL_INVALID_OPERATION,
10966 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10971 gfx::Size size = gl_image->GetSize();
10972 texture_manager()->SetLevelInfo(
10973 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10974 GL_RGBA, GL_UNSIGNED_BYTE, true);
10975 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10978 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10979 GLenum target, GLint image_id) {
10980 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10982 // Default target might be conceptually valid, but disallow it to avoid
10984 TextureRef* texture_ref =
10985 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10986 if (!texture_ref) {
10987 LOCAL_SET_GL_ERROR(
10988 GL_INVALID_OPERATION,
10989 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10993 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10995 LOCAL_SET_GL_ERROR(
10996 GL_INVALID_OPERATION,
10997 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
11001 // Do nothing when image is not currently bound.
11002 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
11006 ScopedGLErrorSuppressor suppressor(
11007 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
11008 gl_image->ReleaseTexImage(target);
11011 texture_manager()->SetLevelInfo(
11012 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
11013 GL_RGBA, GL_UNSIGNED_BYTE, false);
11016 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
11017 uint32 immediate_data_size,
11018 const void* cmd_data) {
11019 const gles2::cmds::TraceBeginCHROMIUM& c =
11020 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
11021 Bucket* bucket = GetBucket(c.bucket_id);
11022 if (!bucket || bucket->size() == 0) {
11023 return error::kInvalidArguments;
11025 std::string command_name;
11026 if (!bucket->GetAsString(&command_name)) {
11027 return error::kInvalidArguments;
11029 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
11030 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
11031 LOCAL_SET_GL_ERROR(
11032 GL_INVALID_OPERATION,
11033 "glTraceBeginCHROMIUM", "unable to create begin trace");
11034 return error::kNoError;
11036 return error::kNoError;
11039 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
11040 if (gpu_tracer_->CurrentName().empty()) {
11041 LOCAL_SET_GL_ERROR(
11042 GL_INVALID_OPERATION,
11043 "glTraceEndCHROMIUM", "no trace begin found");
11046 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
11047 gpu_tracer_->End(kTraceCHROMIUM);
11050 void GLES2DecoderImpl::DoDrawBuffersEXT(
11051 GLsizei count, const GLenum* bufs) {
11052 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
11053 LOCAL_SET_GL_ERROR(
11055 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
11059 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
11061 for (GLsizei i = 0; i < count; ++i) {
11062 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
11063 bufs[i] != GL_NONE) {
11064 LOCAL_SET_GL_ERROR(
11065 GL_INVALID_OPERATION,
11066 "glDrawBuffersEXT",
11067 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
11071 glDrawBuffersARB(count, bufs);
11072 framebuffer->SetDrawBuffers(count, bufs);
11073 } else { // backbuffer
11075 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
11076 LOCAL_SET_GL_ERROR(
11077 GL_INVALID_OPERATION,
11078 "glDrawBuffersEXT",
11079 "more than one buffer or bufs not GL_NONE or GL_BACK");
11082 GLenum mapped_buf = bufs[0];
11083 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
11084 bufs[0] == GL_BACK) {
11085 mapped_buf = GL_COLOR_ATTACHMENT0;
11087 glDrawBuffersARB(count, &mapped_buf);
11088 group_->set_draw_buffer(bufs[0]);
11092 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
11093 group_->LoseContexts(other);
11094 reset_status_ = current;
11095 current_decoder_error_ = error::kLostContext;
11098 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
11099 const GLfloat* matrix) {
11100 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
11101 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
11102 if (!features().chromium_path_rendering) {
11103 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11104 "glMatrixLoadfCHROMIUM",
11105 "function not available");
11109 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
11110 ? state_.projection_matrix
11111 : state_.modelview_matrix;
11112 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
11113 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11114 // since the values of the _NV and _CHROMIUM tokens match.
11115 glMatrixLoadfEXT(matrix_mode, matrix);
11118 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
11119 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
11120 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
11122 if (!features().chromium_path_rendering) {
11123 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11124 "glMatrixLoadIdentityCHROMIUM",
11125 "function not available");
11129 static GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
11130 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
11131 0.0f, 0.0f, 0.0f, 1.0f};
11133 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
11134 ? state_.projection_matrix
11135 : state_.modelview_matrix;
11136 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
11137 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11138 // since the values of the _NV and _CHROMIUM tokens match.
11139 glMatrixLoadIdentityEXT(matrix_mode);
11142 bool GLES2DecoderImpl::ValidateAsyncTransfer(
11143 const char* function_name,
11144 TextureRef* texture_ref,
11147 const void * data) {
11148 // We only support async uploads to 2D textures for now.
11149 if (GL_TEXTURE_2D != target) {
11150 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
11153 // We only support uploads to level zero for now.
11155 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
11158 // A transfer buffer must be bound, even for asyncTexImage2D.
11159 if (data == NULL) {
11160 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
11163 // We only support one async transfer in progress.
11164 if (!texture_ref ||
11165 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
11166 LOCAL_SET_GL_ERROR(
11167 GL_INVALID_OPERATION,
11168 function_name, "transfer already in progress");
11174 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
11175 uint32 async_upload_token,
11176 uint32 sync_data_shm_id,
11177 uint32 sync_data_shm_offset) {
11178 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
11179 if (!buffer.get() ||
11180 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
11181 return base::Closure();
11183 AsyncMemoryParams mem_params(buffer,
11184 sync_data_shm_offset,
11185 sizeof(AsyncUploadSync));
11187 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
11188 new AsyncUploadTokenCompletionObserver(async_upload_token));
11191 &AsyncPixelTransferManager::AsyncNotifyCompletion,
11192 base::Unretained(GetAsyncPixelTransferManager()),
11197 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
11198 uint32 immediate_data_size,
11199 const void* cmd_data) {
11200 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
11201 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
11202 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
11203 GLenum target = static_cast<GLenum>(c.target);
11204 GLint level = static_cast<GLint>(c.level);
11205 GLenum internal_format = static_cast<GLenum>(c.internalformat);
11206 GLsizei width = static_cast<GLsizei>(c.width);
11207 GLsizei height = static_cast<GLsizei>(c.height);
11208 GLint border = static_cast<GLint>(c.border);
11209 GLenum format = static_cast<GLenum>(c.format);
11210 GLenum type = static_cast<GLenum>(c.type);
11211 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
11212 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
11213 uint32 pixels_size;
11214 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11215 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11216 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11218 base::ScopedClosureRunner scoped_completion_callback;
11219 if (async_upload_token) {
11220 base::Closure completion_closure =
11221 AsyncUploadTokenCompletionClosure(async_upload_token,
11223 sync_data_shm_offset);
11224 if (completion_closure.is_null())
11225 return error::kInvalidArguments;
11227 scoped_completion_callback.Reset(completion_closure);
11230 // TODO(epenner): Move this and copies of this memory validation
11231 // into ValidateTexImage2D step.
11232 if (!GLES2Util::ComputeImageDataSizes(
11233 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
11235 return error::kOutOfBounds;
11237 const void* pixels = NULL;
11238 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
11239 pixels = GetSharedMemoryAs<const void*>(
11240 pixels_shm_id, pixels_shm_offset, pixels_size);
11242 return error::kOutOfBounds;
11246 TextureManager::DoTextImage2DArguments args = {
11247 target, level, internal_format, width, height, border, format, type,
11248 pixels, pixels_size};
11249 TextureRef* texture_ref;
11250 // All the normal glTexSubImage2D validation.
11251 if (!texture_manager()->ValidateTexImage2D(
11252 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
11253 return error::kNoError;
11256 // Extra async validation.
11257 Texture* texture = texture_ref->texture();
11258 if (!ValidateAsyncTransfer(
11259 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
11260 return error::kNoError;
11262 // Don't allow async redefinition of a textures.
11263 if (texture->IsDefined()) {
11264 LOCAL_SET_GL_ERROR(
11265 GL_INVALID_OPERATION,
11266 "glAsyncTexImage2DCHROMIUM", "already defined");
11267 return error::kNoError;
11270 if (!EnsureGPUMemoryAvailable(pixels_size)) {
11271 LOCAL_SET_GL_ERROR(
11272 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
11273 return error::kNoError;
11276 // Setup the parameters.
11277 AsyncTexImage2DParams tex_params = {
11278 target, level, static_cast<GLenum>(internal_format),
11279 width, height, border, format, type};
11280 AsyncMemoryParams mem_params(
11281 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
11283 // Set up the async state if needed, and make the texture
11284 // immutable so the async state stays valid. The level info
11285 // is set up lazily when the transfer completes.
11286 AsyncPixelTransferDelegate* delegate =
11287 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
11289 texture->SetImmutable(true);
11291 delegate->AsyncTexImage2D(
11294 base::Bind(&TextureManager::SetLevelInfoFromParams,
11295 // The callback is only invoked if the transfer delegate still
11296 // exists, which implies through manager->texture_ref->state
11297 // ownership that both of these pointers are valid.
11298 base::Unretained(texture_manager()),
11299 base::Unretained(texture_ref),
11301 return error::kNoError;
11304 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
11305 uint32 immediate_data_size,
11306 const void* cmd_data) {
11307 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
11308 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
11309 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
11310 GLenum target = static_cast<GLenum>(c.target);
11311 GLint level = static_cast<GLint>(c.level);
11312 GLint xoffset = static_cast<GLint>(c.xoffset);
11313 GLint yoffset = static_cast<GLint>(c.yoffset);
11314 GLsizei width = static_cast<GLsizei>(c.width);
11315 GLsizei height = static_cast<GLsizei>(c.height);
11316 GLenum format = static_cast<GLenum>(c.format);
11317 GLenum type = static_cast<GLenum>(c.type);
11318 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11319 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11320 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11322 base::ScopedClosureRunner scoped_completion_callback;
11323 if (async_upload_token) {
11324 base::Closure completion_closure =
11325 AsyncUploadTokenCompletionClosure(async_upload_token,
11327 sync_data_shm_offset);
11328 if (completion_closure.is_null())
11329 return error::kInvalidArguments;
11331 scoped_completion_callback.Reset(completion_closure);
11334 // TODO(epenner): Move this and copies of this memory validation
11335 // into ValidateTexSubImage2D step.
11337 if (!GLES2Util::ComputeImageDataSizes(
11338 width, height, format, type, state_.unpack_alignment, &data_size,
11340 return error::kOutOfBounds;
11342 const void* pixels = GetSharedMemoryAs<const void*>(
11343 c.data_shm_id, c.data_shm_offset, data_size);
11345 // All the normal glTexSubImage2D validation.
11346 error::Error error = error::kNoError;
11347 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
11348 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
11352 // Extra async validation.
11353 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11355 Texture* texture = texture_ref->texture();
11356 if (!ValidateAsyncTransfer(
11357 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
11358 return error::kNoError;
11360 // Guarantee async textures are always 'cleared' as follows:
11361 // - AsyncTexImage2D can not redefine an existing texture
11362 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
11363 // - AsyncTexSubImage2D clears synchronously if not already cleared.
11364 // - Textures become immutable after an async call.
11365 // This way we know in all cases that an async texture is always clear.
11366 if (!texture->SafeToRenderFrom()) {
11367 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
11369 LOCAL_SET_GL_ERROR(
11371 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
11372 return error::kNoError;
11376 // Setup the parameters.
11377 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
11378 width, height, format, type};
11379 AsyncMemoryParams mem_params(
11380 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
11381 AsyncPixelTransferDelegate* delegate =
11382 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11384 // TODO(epenner): We may want to enforce exclusive use
11385 // of async APIs in which case this should become an error,
11386 // (the texture should have been async defined).
11387 AsyncTexImage2DParams define_params = {target, level,
11389 texture->GetLevelSize(target, level, &define_params.width,
11390 &define_params.height);
11391 texture->GetLevelType(target, level, &define_params.type,
11392 &define_params.internal_format);
11393 // Set up the async state if needed, and make the texture
11394 // immutable so the async state stays valid.
11395 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
11396 texture_ref, define_params);
11397 texture->SetImmutable(true);
11400 delegate->AsyncTexSubImage2D(tex_params, mem_params);
11401 return error::kNoError;
11404 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
11405 uint32 immediate_data_size,
11406 const void* cmd_data) {
11407 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
11408 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
11409 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11410 GLenum target = static_cast<GLenum>(c.target);
11412 if (GL_TEXTURE_2D != target) {
11413 LOCAL_SET_GL_ERROR(
11414 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
11415 return error::kNoError;
11417 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11419 if (!texture_ref) {
11420 LOCAL_SET_GL_ERROR(
11421 GL_INVALID_OPERATION,
11422 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
11423 return error::kNoError;
11425 AsyncPixelTransferDelegate* delegate =
11426 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11428 LOCAL_SET_GL_ERROR(
11429 GL_INVALID_OPERATION,
11430 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
11431 return error::kNoError;
11433 delegate->WaitForTransferCompletion();
11434 ProcessFinishedAsyncTransfers();
11435 return error::kNoError;
11438 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
11439 uint32 immediate_data_size,
11440 const void* data) {
11441 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11443 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
11444 ProcessFinishedAsyncTransfers();
11445 return error::kNoError;
11448 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
11449 TextureRef* texture_ref) {
11450 Texture* texture = texture_ref->texture();
11451 DoDidUseTexImageIfNeeded(texture, texture->target());
11454 void GLES2DecoderImpl::OnContextLostError() {
11455 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
11458 void GLES2DecoderImpl::OnOutOfMemoryError() {
11459 if (lose_context_when_out_of_memory_) {
11460 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
11464 // Include the auto-generated part of this file. We split this because it means
11465 // we can easily edit the non-auto generated parts right here in this file
11466 // instead of having to edit some template or the code generator.
11467 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
11469 } // namespace gles2