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/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/id_allocator.h"
32 #include "gpu/command_buffer/common/mailbox.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
35 #include "gpu/command_buffer/service/buffer_manager.h"
36 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
37 #include "gpu/command_buffer/service/context_group.h"
38 #include "gpu/command_buffer/service/context_state.h"
39 #include "gpu/command_buffer/service/error_state.h"
40 #include "gpu/command_buffer/service/feature_info.h"
41 #include "gpu/command_buffer/service/framebuffer_manager.h"
42 #include "gpu/command_buffer/service/gl_utils.h"
43 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
44 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
45 #include "gpu/command_buffer/service/gpu_state_tracer.h"
46 #include "gpu/command_buffer/service/gpu_switches.h"
47 #include "gpu/command_buffer/service/gpu_tracer.h"
48 #include "gpu/command_buffer/service/image_manager.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/program_manager.h"
52 #include "gpu/command_buffer/service/query_manager.h"
53 #include "gpu/command_buffer/service/renderbuffer_manager.h"
54 #include "gpu/command_buffer/service/shader_manager.h"
55 #include "gpu/command_buffer/service/shader_translator.h"
56 #include "gpu/command_buffer/service/shader_translator_cache.h"
57 #include "gpu/command_buffer/service/texture_manager.h"
58 #include "gpu/command_buffer/service/vertex_array_manager.h"
59 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
60 #include "third_party/smhasher/src/City.h"
61 #include "ui/gl/gl_bindings.h"
62 #include "ui/gl/gl_fence.h"
63 #include "ui/gl/gl_image.h"
64 #include "ui/gl/gl_implementation.h"
65 #include "ui/gl/gl_surface.h"
67 #if defined(OS_MACOSX)
68 #include "ui/gl/io_surface_support_mac.h"
72 #include "base/win/win_util.h"
80 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
81 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
82 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
83 static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
85 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
86 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
87 return static_cast<khronos_uint64_t>(
88 CityHash64(name, static_cast<size_t>(len)));
92 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
95 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
98 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
99 GLenum precision_type,
100 GLint *range, GLint *precision) {
101 switch (precision_type) {
105 // These values are for a 32-bit twos-complement integer format.
111 case GL_MEDIUM_FLOAT:
113 // These values are for an IEEE single-precision floating-point format.
123 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
124 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
125 // This function is sometimes defined even though it's really just
126 // a stub, so we need to set range and precision as if it weren't
127 // defined before calling it.
128 // On Mac OS with some GPUs, calling this generates a
129 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
131 glGetShaderPrecisionFormat(shader_type, precision_type,
134 // TODO(brianderson): Make the following official workarounds.
136 // Some drivers have bugs where they report the ranges as a negative number.
137 // Taking the absolute value here shouldn't hurt because negative numbers
138 // aren't expected anyway.
139 range[0] = abs(range[0]);
140 range[1] = abs(range[1]);
142 // If the driver reports a precision for highp float that isn't actually
143 // highp, don't pretend like it's supported because shader compilation will
145 if (precision_type == GL_HIGH_FLOAT &&
146 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
156 class GLES2DecoderImpl;
158 // Local versions of the SET_GL_ERROR macros
159 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
160 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
161 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
162 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
163 function_name, value, label)
164 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
165 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
166 function_name, pname)
167 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
168 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
170 #define LOCAL_PEEK_GL_ERROR(function_name) \
171 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
172 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
173 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
174 #define LOCAL_PERFORMANCE_WARNING(msg) \
175 PerformanceWarning(__FILE__, __LINE__, msg)
176 #define LOCAL_RENDER_WARNING(msg) \
177 RenderWarning(__FILE__, __LINE__, msg)
179 // Check that certain assumptions the code makes are true. There are places in
180 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
181 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
182 // a few others) are 32bits. If they are not 32bits the code will have to change
183 // to call those GL functions with service side memory and then copy the results
184 // to shared memory, converting the sizes.
185 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
186 GLint_not_same_size_as_uint32);
187 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
188 GLint_not_same_size_as_uint32);
189 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
190 GLfloat_not_same_size_as_float);
192 // TODO(kbr): the use of this anonymous namespace core dumps the
193 // linker on Mac OS X 10.6 when the symbol ordering file is used
196 // Returns the address of the first byte after a struct.
197 template <typename T>
198 const void* AddressAfterStruct(const T& pod) {
199 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
202 // Returns the address of the frst byte after the struct or NULL if size >
203 // immediate_data_size.
204 template <typename RETURN_TYPE, typename COMMAND_TYPE>
205 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
207 uint32 immediate_data_size) {
208 return (size <= immediate_data_size) ?
209 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
213 // Computes the data size for certain gl commands like glUniform.
214 bool ComputeDataSize(
217 unsigned int elements_per_unit,
220 if (!SafeMultiplyUint32(count, size, &value)) {
223 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
230 // A struct to hold info about each command.
232 uint8 arg_flags; // How to handle the arguments for this command
233 uint8 cmd_flags; // How to handle this command
234 uint16 arg_count; // How many arguments are expected for this command.
237 // cmds::name::cmd_flags,
238 // A table of CommandInfo for all the commands.
239 const CommandInfo g_command_info[] = {
240 #define GLES2_CMD_OP(name) { \
241 cmds::name::kArgFlags, \
242 cmds::name::cmd_flags, \
243 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
245 GLES2_COMMAND_LIST(GLES2_CMD_OP)
250 // Return true if a character belongs to the ASCII subset as defined in
251 // GLSL ES 1.0 spec section 3.1.
252 static bool CharacterIsValidForGLES(unsigned char c) {
253 // Printing characters are valid except " $ ` @ \ ' DEL.
254 if (c >= 32 && c <= 126 &&
263 // Horizontal tab, line feed, vertical tab, form feed, carriage return
265 if (c >= 9 && c <= 13) {
272 static bool StringIsValidForGLES(const char* str) {
273 for (; *str; ++str) {
274 if (!CharacterIsValidForGLES(*str)) {
281 // This class prevents any GL errors that occur when it is in scope from
282 // being reported to the client.
283 class ScopedGLErrorSuppressor {
285 explicit ScopedGLErrorSuppressor(
286 const char* function_name, ErrorState* error_state);
287 ~ScopedGLErrorSuppressor();
289 const char* function_name_;
290 ErrorState* error_state_;
291 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
294 // Temporarily changes a decoder's bound texture and restore it when this
295 // object goes out of scope. Also temporarily switches to using active texture
296 // unit zero in case the client has changed that to something invalid.
297 class ScopedTextureBinder {
299 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
300 ~ScopedTextureBinder();
303 ContextState* state_;
305 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
308 // Temporarily changes a decoder's bound render buffer and restore it when this
309 // object goes out of scope.
310 class ScopedRenderBufferBinder {
312 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
313 ~ScopedRenderBufferBinder();
316 ContextState* state_;
317 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
320 // Temporarily changes a decoder's bound frame buffer and restore it when this
321 // object goes out of scope.
322 class ScopedFrameBufferBinder {
324 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
325 ~ScopedFrameBufferBinder();
328 GLES2DecoderImpl* decoder_;
329 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
332 // Temporarily changes a decoder's bound frame buffer to a resolved version of
333 // the multisampled offscreen render buffer if that buffer is multisampled, and,
334 // if it is bound or enforce_internal_framebuffer is true. If internal is
335 // true, the resolved framebuffer is not visible to the parent.
336 class ScopedResolvedFrameBufferBinder {
338 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
339 bool enforce_internal_framebuffer,
341 ~ScopedResolvedFrameBufferBinder();
344 GLES2DecoderImpl* decoder_;
345 bool resolve_and_bind_;
346 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
349 class ScopedModifyPixels {
351 explicit ScopedModifyPixels(TextureRef* ref);
352 ~ScopedModifyPixels();
358 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
360 ref_->texture()->OnWillModifyPixels();
363 ScopedModifyPixels::~ScopedModifyPixels() {
365 ref_->texture()->OnDidModifyPixels();
368 class ScopedRenderTo {
370 explicit ScopedRenderTo(Framebuffer* framebuffer);
374 const Framebuffer* framebuffer_;
377 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
378 : framebuffer_(framebuffer) {
380 framebuffer_->OnWillRenderTo();
383 ScopedRenderTo::~ScopedRenderTo() {
385 framebuffer_->OnDidRenderTo();
388 // Encapsulates an OpenGL texture.
391 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
394 // Create a new render texture.
397 // Set the initial size and format of a render texture or resize it.
398 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
400 // Copy the contents of the currently bound frame buffer.
401 void Copy(const gfx::Size& size, GLenum format);
403 // Destroy the render texture. This must be explicitly called before
404 // destroying this object.
407 // Invalidate the texture. This can be used when a context is lost and it is
408 // not possible to make it current in order to free the resource.
415 gfx::Size size() const {
420 MemoryTypeTracker memory_tracker_;
421 ContextState* state_;
422 size_t bytes_allocated_;
425 DISALLOW_COPY_AND_ASSIGN(BackTexture);
428 // Encapsulates an OpenGL render buffer of any format.
429 class BackRenderbuffer {
431 explicit BackRenderbuffer(
432 RenderbufferManager* renderbuffer_manager,
433 MemoryTracker* memory_tracker,
434 ContextState* state);
437 // Create a new render buffer.
440 // Set the initial size and format of a render buffer or resize it.
441 bool AllocateStorage(const FeatureInfo* feature_info,
442 const gfx::Size& size,
446 // Destroy the render buffer. This must be explicitly called before destroying
450 // Invalidate the render buffer. This can be used when a context is lost and
451 // it is not possible to make it current in order to free the resource.
459 RenderbufferManager* renderbuffer_manager_;
460 MemoryTypeTracker memory_tracker_;
461 ContextState* state_;
462 size_t bytes_allocated_;
464 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
467 // Encapsulates an OpenGL frame buffer.
468 class BackFramebuffer {
470 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
473 // Create a new frame buffer.
476 // Attach a color render buffer to a frame buffer.
477 void AttachRenderTexture(BackTexture* texture);
479 // Attach a render buffer to a frame buffer. Note that this unbinds any
480 // currently bound frame buffer.
481 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
483 // Destroy the frame buffer. This must be explicitly called before destroying
487 // Invalidate the frame buffer. This can be used when a context is lost and it
488 // is not possible to make it current in order to free the resource.
491 // See glCheckFramebufferStatusEXT.
492 GLenum CheckStatus();
499 GLES2DecoderImpl* decoder_;
501 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
504 struct FenceCallback {
505 explicit FenceCallback()
506 : fence(gfx::GLFence::Create()) {
509 std::vector<base::Closure> callbacks;
510 scoped_ptr<gfx::GLFence> fence;
513 class AsyncUploadTokenCompletionObserver
514 : public AsyncPixelTransferCompletionObserver {
516 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
517 : async_upload_token_(async_upload_token) {
520 virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
521 DCHECK(mem_params.buffer());
522 void* data = mem_params.GetDataAddress();
523 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
524 sync->SetAsyncUploadToken(async_upload_token_);
528 virtual ~AsyncUploadTokenCompletionObserver() {
531 uint32 async_upload_token_;
533 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
536 // } // anonymous namespace.
538 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
539 uint32* service_texture_id) {
543 GLES2Decoder::GLES2Decoder()
544 : initialized_(false),
546 log_commands_(false) {
549 GLES2Decoder::~GLES2Decoder() {
552 void GLES2Decoder::BeginDecoding() {}
554 void GLES2Decoder::EndDecoding() {}
556 // This class implements GLES2Decoder so we don't have to expose all the GLES2
557 // cmd stuff to outside this class.
558 class GLES2DecoderImpl : public GLES2Decoder,
559 public FramebufferManager::TextureDetachObserver,
560 public ErrorStateClient {
562 explicit GLES2DecoderImpl(ContextGroup* group);
563 virtual ~GLES2DecoderImpl();
565 // Overridden from AsyncAPIInterface.
566 virtual Error DoCommand(unsigned int command,
567 unsigned int arg_count,
568 const void* args) OVERRIDE;
570 // Overridden from AsyncAPIInterface.
571 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
573 // Overridden from GLES2Decoder.
574 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
575 const scoped_refptr<gfx::GLContext>& context,
577 const gfx::Size& size,
578 const DisallowedFeatures& disallowed_features,
579 const std::vector<int32>& attribs) OVERRIDE;
580 virtual void Destroy(bool have_context) OVERRIDE;
581 virtual void SetSurface(
582 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
583 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
584 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
585 void UpdateParentTextureInfo();
586 virtual bool MakeCurrent() OVERRIDE;
587 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
588 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
589 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
590 virtual Capabilities GetCapabilities() OVERRIDE;
591 virtual void RestoreState(const ContextState* prev_state) const OVERRIDE;
593 virtual void RestoreActiveTexture() const OVERRIDE {
594 state_.RestoreActiveTexture();
596 virtual void RestoreAllTextureUnitBindings(
597 const ContextState* prev_state) const OVERRIDE {
598 state_.RestoreAllTextureUnitBindings(prev_state);
600 virtual void RestoreActiveTextureUnitBinding(
601 unsigned int target) const OVERRIDE {
602 state_.RestoreActiveTextureUnitBinding(target);
604 virtual void RestoreBufferBindings() const OVERRIDE {
605 state_.RestoreBufferBindings();
607 virtual void RestoreGlobalState() const OVERRIDE {
608 state_.RestoreGlobalState(NULL);
610 virtual void RestoreProgramBindings() const OVERRIDE {
611 state_.RestoreProgramBindings();
613 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
614 state_.RestoreTextureUnitBindings(unit, NULL);
616 virtual void RestoreFramebufferBindings() const OVERRIDE;
617 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
619 virtual void ClearAllAttributes() const OVERRIDE;
620 virtual void RestoreAllAttributes() const OVERRIDE;
622 virtual QueryManager* GetQueryManager() OVERRIDE {
623 return query_manager_.get();
625 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
626 return vertex_array_manager_.get();
628 virtual bool ProcessPendingQueries() OVERRIDE;
629 virtual bool HasMoreIdleWork() OVERRIDE;
630 virtual void PerformIdleWork() OVERRIDE;
632 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
634 virtual void SetResizeCallback(
635 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
637 virtual Logger* GetLogger() OVERRIDE;
639 virtual void BeginDecoding() OVERRIDE;
640 virtual void EndDecoding() OVERRIDE;
642 virtual ErrorState* GetErrorState() OVERRIDE;
643 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
645 virtual void SetShaderCacheCallback(
646 const ShaderCacheCallback& callback) OVERRIDE;
647 virtual void SetWaitSyncPointCallback(
648 const WaitSyncPointCallback& callback) OVERRIDE;
650 virtual AsyncPixelTransferManager*
651 GetAsyncPixelTransferManager() OVERRIDE;
652 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
653 virtual void SetAsyncPixelTransferManagerForTest(
654 AsyncPixelTransferManager* manager) OVERRIDE;
655 virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
656 void ProcessFinishedAsyncTransfers();
658 virtual bool GetServiceTextureId(uint32 client_texture_id,
659 uint32* service_texture_id) OVERRIDE;
661 virtual uint32 GetTextureUploadCount() OVERRIDE;
662 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
663 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
664 virtual 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 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
682 // Overridden from FramebufferManager::TextureDetachObserver:
683 virtual void OnTextureRefDetachedFromFramebuffer(
684 TextureRef* texture) OVERRIDE;
686 // Overriden from ErrorStateClient.
687 virtual void OnOutOfMemoryError() OVERRIDE;
689 // Helpers to facilitate calling into compatible extensions.
690 static void RenderbufferStorageMultisampleHelper(
691 const FeatureInfo* feature_info,
694 GLenum internal_format,
698 void BlitFramebufferHelper(GLint srcX0,
710 friend class ScopedFrameBufferBinder;
711 friend class ScopedResolvedFrameBufferBinder;
712 friend class BackFramebuffer;
714 // Initialize or re-initialize the shader translator.
715 bool InitializeShaderTranslator();
717 void UpdateCapabilities();
719 // Helpers for the glGen and glDelete functions.
720 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
721 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
722 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
723 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
724 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
725 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
726 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
727 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
728 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
729 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
730 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
731 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
733 // Helper for async upload token completion notification callback.
734 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
735 uint32 sync_data_shm_id,
736 uint32 sync_data_shm_offset);
741 void OnFboChanged() const;
742 void OnUseFramebuffer() const;
744 // TODO(gman): Cache these pointers?
745 BufferManager* buffer_manager() {
746 return group_->buffer_manager();
749 RenderbufferManager* renderbuffer_manager() {
750 return group_->renderbuffer_manager();
753 FramebufferManager* framebuffer_manager() {
754 return group_->framebuffer_manager();
757 ProgramManager* program_manager() {
758 return group_->program_manager();
761 ShaderManager* shader_manager() {
762 return group_->shader_manager();
765 ShaderTranslatorCache* shader_translator_cache() {
766 return group_->shader_translator_cache();
769 const TextureManager* texture_manager() const {
770 return group_->texture_manager();
773 TextureManager* texture_manager() {
774 return group_->texture_manager();
777 MailboxManager* mailbox_manager() {
778 return group_->mailbox_manager();
781 ImageManager* image_manager() {
782 return group_->image_manager();
785 VertexArrayManager* vertex_array_manager() {
786 return vertex_array_manager_.get();
789 MemoryTracker* memory_tracker() {
790 return group_->memory_tracker();
793 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
794 MemoryTracker* tracker = memory_tracker();
796 return tracker->EnsureGPUMemoryAvailable(estimated_size);
801 bool IsOffscreenBufferMultisampled() const {
802 return offscreen_target_samples_ > 1;
805 // Creates a Texture for the given texture.
806 TextureRef* CreateTexture(
807 GLuint client_id, GLuint service_id) {
808 return texture_manager()->CreateTexture(client_id, service_id);
811 // Gets the texture info for the given texture. Returns NULL if none exists.
812 TextureRef* GetTexture(GLuint client_id) const {
813 return texture_manager()->GetTexture(client_id);
816 // Deletes the texture info for the given texture.
817 void RemoveTexture(GLuint client_id) {
818 texture_manager()->RemoveTexture(client_id);
821 // Get the size (in pixels) of the currently bound frame buffer (either FBO
822 // or regular back buffer).
823 gfx::Size GetBoundReadFrameBufferSize();
825 // Get the format of the currently bound frame buffer (either FBO or regular
827 GLenum GetBoundReadFrameBufferTextureType();
828 GLenum GetBoundReadFrameBufferInternalFormat();
829 GLenum GetBoundDrawFrameBufferInternalFormat();
831 // Wrapper for CompressedTexImage2D commands.
832 error::Error DoCompressedTexImage2D(
835 GLenum internal_format,
842 // Wrapper for CompressedTexSubImage2D.
843 void DoCompressedTexSubImage2D(
854 // Wrapper for CopyTexImage2D.
855 void DoCopyTexImage2D(
858 GLenum internal_format,
865 // Wrapper for SwapBuffers.
866 void DoSwapBuffers();
868 // Wrapper for CopyTexSubImage2D.
869 void DoCopyTexSubImage2D(
879 // Validation for TexSubImage2D.
880 bool ValidateTexSubImage2D(
882 const char* function_name,
893 // Wrapper for TexSubImage2D.
894 error::Error DoTexSubImage2D(
905 // Extra validation for async tex(Sub)Image2D.
906 bool ValidateAsyncTransfer(
907 const char* function_name,
908 TextureRef* texture_ref,
913 // Wrapper for TexImageIOSurface2DCHROMIUM.
914 void DoTexImageIOSurface2DCHROMIUM(
918 GLuint io_surface_id,
921 void DoCopyTextureCHROMIUM(
926 GLenum internal_format,
929 // Wrapper for TexStorage2DEXT.
930 void DoTexStorage2DEXT(
933 GLenum internal_format,
937 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
938 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
940 void DoBindTexImage2DCHROMIUM(
943 void DoReleaseTexImage2DCHROMIUM(
947 void DoTraceEndCHROMIUM(void);
949 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
951 // Creates a Program for the given program.
952 Program* CreateProgram(
953 GLuint client_id, GLuint service_id) {
954 return program_manager()->CreateProgram(client_id, service_id);
957 // Gets the program info for the given program. Returns NULL if none exists.
958 Program* GetProgram(GLuint client_id) {
959 return program_manager()->GetProgram(client_id);
963 void LogClientServiceMapping(
964 const char* /* function_name */,
965 GLuint /* client_id */,
966 GLuint /* service_id */) {
969 void LogClientServiceForInfo(
970 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
973 void LogClientServiceMapping(
974 const char* function_name, GLuint client_id, GLuint service_id) {
975 if (service_logging_) {
976 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
977 << ": client_id = " << client_id
978 << ", service_id = " << service_id;
982 void LogClientServiceForInfo(
983 T* info, GLuint client_id, const char* function_name) {
985 LogClientServiceMapping(function_name, client_id, info->service_id());
990 // Gets the program info for the given program. If it's not a program
991 // generates a GL error. Returns NULL if not program.
992 Program* GetProgramInfoNotShader(
993 GLuint client_id, const char* function_name) {
994 Program* program = GetProgram(client_id);
996 if (GetShader(client_id)) {
998 GL_INVALID_OPERATION, function_name, "shader passed for program");
1000 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1003 LogClientServiceForInfo(program, client_id, function_name);
1008 // Creates a Shader for the given shader.
1009 Shader* CreateShader(
1012 GLenum shader_type) {
1013 return shader_manager()->CreateShader(
1014 client_id, service_id, shader_type);
1017 // Gets the shader info for the given shader. Returns NULL if none exists.
1018 Shader* GetShader(GLuint client_id) {
1019 return shader_manager()->GetShader(client_id);
1022 // Gets the shader info for the given shader. If it's not a shader generates a
1023 // GL error. Returns NULL if not shader.
1024 Shader* GetShaderInfoNotProgram(
1025 GLuint client_id, const char* function_name) {
1026 Shader* shader = GetShader(client_id);
1028 if (GetProgram(client_id)) {
1030 GL_INVALID_OPERATION, function_name, "program passed for shader");
1033 GL_INVALID_VALUE, function_name, "unknown shader");
1036 LogClientServiceForInfo(shader, client_id, function_name);
1040 // Creates a buffer info for the given buffer.
1041 void CreateBuffer(GLuint client_id, GLuint service_id) {
1042 return buffer_manager()->CreateBuffer(client_id, service_id);
1045 // Gets the buffer info for the given buffer.
1046 Buffer* GetBuffer(GLuint client_id) {
1047 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1051 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1052 // on glDeleteBuffers so we can make sure the user does not try to render
1053 // with deleted buffers.
1054 void RemoveBuffer(GLuint client_id);
1056 // Creates a framebuffer info for the given framebuffer.
1057 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1058 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1061 // Gets the framebuffer info for the given framebuffer.
1062 Framebuffer* GetFramebuffer(GLuint client_id) {
1063 return framebuffer_manager()->GetFramebuffer(client_id);
1066 // Removes the framebuffer info for the given framebuffer.
1067 void RemoveFramebuffer(GLuint client_id) {
1068 framebuffer_manager()->RemoveFramebuffer(client_id);
1071 // Creates a renderbuffer info for the given renderbuffer.
1072 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1073 return renderbuffer_manager()->CreateRenderbuffer(
1074 client_id, service_id);
1077 // Gets the renderbuffer info for the given renderbuffer.
1078 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1079 return renderbuffer_manager()->GetRenderbuffer(client_id);
1082 // Removes the renderbuffer info for the given renderbuffer.
1083 void RemoveRenderbuffer(GLuint client_id) {
1084 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1087 // Gets the vertex attrib manager for the given vertex array.
1088 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1089 VertexAttribManager* info =
1090 vertex_array_manager()->GetVertexAttribManager(client_id);
1094 // Removes the vertex attrib manager for the given vertex array.
1095 void RemoveVertexAttribManager(GLuint client_id) {
1096 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1099 // Creates a vertex attrib manager for the given vertex array.
1100 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1103 bool client_visible) {
1104 return vertex_array_manager()->CreateVertexAttribManager(
1105 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1108 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1109 void DoBindUniformLocationCHROMIUM(
1110 GLuint client_id, GLint location, const char* name);
1112 error::Error GetAttribLocationHelper(
1113 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1114 const std::string& name_str);
1116 error::Error GetUniformLocationHelper(
1117 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1118 const std::string& name_str);
1120 // Helper for glShaderSource.
1121 error::Error ShaderSourceHelper(
1122 GLuint client_id, const char* data, uint32 data_size);
1124 // Clear any textures used by the current program.
1125 bool ClearUnclearedTextures();
1127 // Clears any uncleared attachments attached to the given frame buffer.
1128 // Returns false if there was a generated GL error.
1129 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1131 // overridden from GLES2Decoder
1132 virtual bool ClearLevel(unsigned service_id,
1133 unsigned bind_target,
1136 unsigned internal_format,
1141 bool is_texture_immutable) OVERRIDE;
1143 // Restore all GL state that affects clearing.
1144 void RestoreClearState();
1146 // Remembers the state of some capabilities.
1147 // Returns: true if glEnable/glDisable should actually be called.
1148 bool SetCapabilityState(GLenum cap, bool enabled);
1150 // Check that the currently bound framebuffers are valid.
1151 // Generates GL error if not.
1152 bool CheckBoundFramebuffersValid(const char* func_name);
1154 // Check if a framebuffer meets our requirements.
1155 bool CheckFramebufferValid(
1156 Framebuffer* framebuffer,
1158 const char* func_name);
1160 // Checks if the current program exists and is valid. If not generates the
1161 // appropriate GL error. Returns true if the current program is in a usable
1163 bool CheckCurrentProgram(const char* function_name);
1165 // Checks if the current program exists and is valid and that location is not
1166 // -1. If the current program is not valid generates the appropriate GL
1167 // error. Returns true if the current program is in a usable state and
1168 // location is not -1.
1169 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1171 // Gets the type of a uniform for a location in the current program. Sets GL
1172 // errors if the current program is not valid. Returns true if the current
1173 // program is valid and the location exists. Adjusts count so it
1174 // does not overflow the uniform.
1175 bool PrepForSetUniformByLocation(GLint fake_location,
1176 const char* function_name,
1177 Program::UniformApiType api_type,
1178 GLint* real_location,
1182 // Gets the service id for any simulated backbuffer fbo.
1183 GLuint GetBackbufferServiceId() const;
1185 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1186 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1188 // Helper for glGetVertexAttrib
1189 void GetVertexAttribHelper(
1190 const VertexAttrib* attrib, GLenum pname, GLint* param);
1192 // Wrapper for glCreateProgram
1193 bool CreateProgramHelper(GLuint client_id);
1195 // Wrapper for glCreateShader
1196 bool CreateShaderHelper(GLenum type, GLuint client_id);
1198 // Wrapper for glActiveTexture
1199 void DoActiveTexture(GLenum texture_unit);
1201 // Wrapper for glAttachShader
1202 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1204 // Wrapper for glBindBuffer since we need to track the current targets.
1205 void DoBindBuffer(GLenum target, GLuint buffer);
1207 // Wrapper for glBindFramebuffer since we need to track the current targets.
1208 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1210 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1211 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1213 // Wrapper for glBindTexture since we need to track the current targets.
1214 void DoBindTexture(GLenum target, GLuint texture);
1216 // Wrapper for glBindVertexArrayOES
1217 void DoBindVertexArrayOES(GLuint array);
1218 void EmulateVertexArrayState();
1220 // Wrapper for glBlitFramebufferCHROMIUM.
1221 void DoBlitFramebufferCHROMIUM(
1222 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1223 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1224 GLbitfield mask, GLenum filter);
1226 // Wrapper for glBufferSubData.
1227 void DoBufferSubData(
1228 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1230 // Wrapper for glCheckFramebufferStatus
1231 GLenum DoCheckFramebufferStatus(GLenum target);
1233 // Wrapper for glClear
1234 error::Error DoClear(GLbitfield mask);
1236 // Wrappers for various state.
1237 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1238 void DoSampleCoverage(GLclampf value, GLboolean invert);
1240 // Wrapper for glCompileShader.
1241 void DoCompileShader(GLuint shader);
1243 // Helper for DeleteSharedIdsCHROMIUM commands.
1244 void DoDeleteSharedIdsCHROMIUM(
1245 GLuint namespace_id, GLsizei n, const GLuint* ids);
1247 // Wrapper for glDetachShader
1248 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1250 // Wrapper for glDisable
1251 void DoDisable(GLenum cap);
1253 // Wrapper for glDisableVertexAttribArray.
1254 void DoDisableVertexAttribArray(GLuint index);
1256 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1258 void DoDiscardFramebufferEXT(GLenum target,
1259 GLsizei numAttachments,
1260 const GLenum* attachments);
1262 // Wrapper for glEnable
1263 void DoEnable(GLenum cap);
1265 // Wrapper for glEnableVertexAttribArray.
1266 void DoEnableVertexAttribArray(GLuint index);
1268 // Wrapper for glFinish.
1271 // Wrapper for glFlush.
1274 // Wrapper for glFramebufferRenderbufffer.
1275 void DoFramebufferRenderbuffer(
1276 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1277 GLuint renderbuffer);
1279 // Wrapper for glFramebufferTexture2D.
1280 void DoFramebufferTexture2D(
1281 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1284 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1285 void DoFramebufferTexture2DMultisample(
1286 GLenum target, GLenum attachment, GLenum textarget,
1287 GLuint texture, GLint level, GLsizei samples);
1289 // Common implementation for both DoFramebufferTexture2D wrappers.
1290 void DoFramebufferTexture2DCommon(const char* name,
1291 GLenum target, GLenum attachment, GLenum textarget,
1292 GLuint texture, GLint level, GLsizei samples);
1294 // Wrapper for glGenerateMipmap
1295 void DoGenerateMipmap(GLenum target);
1297 // Helper for GenSharedIdsCHROMIUM commands.
1298 void DoGenSharedIdsCHROMIUM(
1299 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1301 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1302 // to account for different pname values defined in different extension
1304 GLenum AdjustGetPname(GLenum pname);
1306 // Wrapper for DoGetBooleanv.
1307 void DoGetBooleanv(GLenum pname, GLboolean* params);
1309 // Wrapper for DoGetFloatv.
1310 void DoGetFloatv(GLenum pname, GLfloat* params);
1312 // Wrapper for glGetFramebufferAttachmentParameteriv.
1313 void DoGetFramebufferAttachmentParameteriv(
1314 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1316 // Wrapper for glGetIntegerv.
1317 void DoGetIntegerv(GLenum pname, GLint* params);
1319 // Gets the max value in a range in a buffer.
1320 GLuint DoGetMaxValueInBufferCHROMIUM(
1321 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1323 // Wrapper for glGetBufferParameteriv.
1324 void DoGetBufferParameteriv(
1325 GLenum target, GLenum pname, GLint* params);
1327 // Wrapper for glGetProgramiv.
1328 void DoGetProgramiv(
1329 GLuint program_id, GLenum pname, GLint* params);
1331 // Wrapper for glRenderbufferParameteriv.
1332 void DoGetRenderbufferParameteriv(
1333 GLenum target, GLenum pname, GLint* params);
1335 // Wrapper for glGetShaderiv
1336 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1338 // Wrappers for glGetTexParameter.
1339 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1340 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1341 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1343 // Wrappers for glGetVertexAttrib.
1344 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1345 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1347 // Wrappers for glIsXXX functions.
1348 bool DoIsEnabled(GLenum cap);
1349 bool DoIsBuffer(GLuint client_id);
1350 bool DoIsFramebuffer(GLuint client_id);
1351 bool DoIsProgram(GLuint client_id);
1352 bool DoIsRenderbuffer(GLuint client_id);
1353 bool DoIsShader(GLuint client_id);
1354 bool DoIsTexture(GLuint client_id);
1355 bool DoIsVertexArrayOES(GLuint client_id);
1357 // Wrapper for glLinkProgram
1358 void DoLinkProgram(GLuint program);
1360 // Helper for RegisterSharedIdsCHROMIUM.
1361 void DoRegisterSharedIdsCHROMIUM(
1362 GLuint namespace_id, GLsizei n, const GLuint* ids);
1364 // Wrapper for glRenderbufferStorage.
1365 void DoRenderbufferStorage(
1366 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1368 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1369 void DoRenderbufferStorageMultisampleCHROMIUM(
1370 GLenum target, GLsizei samples, GLenum internalformat,
1371 GLsizei width, GLsizei height);
1373 // Handler for glRenderbufferStorageMultisampleEXT
1374 // (multisampled_render_to_texture).
1375 void DoRenderbufferStorageMultisampleEXT(
1376 GLenum target, GLsizei samples, GLenum internalformat,
1377 GLsizei width, GLsizei height);
1379 // Common validation for multisample extensions.
1380 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1381 GLenum internalformat,
1385 // Verifies that the currently bound multisample renderbuffer is valid
1386 // Very slow! Only done on platforms with driver bugs that return invalid
1387 // buffers under memory pressure
1388 bool VerifyMultisampleRenderbufferIntegrity(
1389 GLuint renderbuffer, GLenum format);
1391 // Wrapper for glReleaseShaderCompiler.
1392 void DoReleaseShaderCompiler() { }
1394 // Wrappers for glTexParameter functions.
1395 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1396 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1397 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1398 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1400 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1401 // spec only these 2 functions can be used to set sampler uniforms.
1402 void DoUniform1i(GLint fake_location, GLint v0);
1403 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1404 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1405 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1406 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1408 // Wrappers for glUniformfv because some drivers don't correctly accept
1410 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1411 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1412 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1413 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1415 void DoUniformMatrix2fv(
1416 GLint fake_location, GLsizei count, GLboolean transpose,
1417 const GLfloat* value);
1418 void DoUniformMatrix3fv(
1419 GLint fake_location, GLsizei count, GLboolean transpose,
1420 const GLfloat* value);
1421 void DoUniformMatrix4fv(
1422 GLint fake_location, GLsizei count, GLboolean transpose,
1423 const GLfloat* value);
1425 bool SetVertexAttribValue(
1426 const char* function_name, GLuint index, const GLfloat* value);
1428 // Wrappers for glVertexAttrib??
1429 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1430 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1431 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1432 void DoVertexAttrib4f(
1433 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1434 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1435 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1436 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1437 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1439 // Wrapper for glViewport
1440 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1442 // Wrapper for glUseProgram
1443 void DoUseProgram(GLuint program);
1445 // Wrapper for glValidateProgram.
1446 void DoValidateProgram(GLuint program_client_id);
1448 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1449 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1450 void DoPopGroupMarkerEXT(void);
1452 // Gets the number of values that will be returned by glGetXXX. Returns
1453 // false if pname is unknown.
1454 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1456 // Checks if the current program and vertex attributes are valid for drawing.
1458 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1460 // Returns true if successful, simulated will be true if attrib0 was
1462 bool SimulateAttrib0(
1463 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1464 void RestoreStateForAttrib(GLuint attrib);
1466 // If an image is bound to texture, this will call Will/DidUseTexImage
1468 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1469 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1471 // Returns false if textures were replaced.
1472 bool PrepareTexturesForRender();
1473 void RestoreStateForTextures();
1475 // Returns true if GL_FIXED attribs were simulated.
1476 bool SimulateFixedAttribs(
1477 const char* function_name,
1478 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1479 void RestoreStateForSimulatedFixedAttribs();
1481 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1482 // cases (primcount is 0 for non-instanced).
1483 error::Error DoDrawArrays(
1484 const char* function_name,
1485 bool instanced, GLenum mode, GLint first, GLsizei count,
1487 error::Error DoDrawElements(
1488 const char* function_name,
1489 bool instanced, GLenum mode, GLsizei count, GLenum type,
1490 int32 offset, GLsizei primcount);
1492 GLenum GetBindTargetForSamplerType(GLenum type) {
1493 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1494 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1497 return GL_TEXTURE_2D;
1498 case GL_SAMPLER_CUBE:
1499 return GL_TEXTURE_CUBE_MAP;
1500 case GL_SAMPLER_EXTERNAL_OES:
1501 return GL_TEXTURE_EXTERNAL_OES;
1502 case GL_SAMPLER_2D_RECT_ARB:
1503 return GL_TEXTURE_RECTANGLE_ARB;
1510 // Gets the framebuffer info for a particular target.
1511 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1512 Framebuffer* framebuffer = NULL;
1514 case GL_FRAMEBUFFER:
1515 case GL_DRAW_FRAMEBUFFER_EXT:
1516 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1518 case GL_READ_FRAMEBUFFER_EXT:
1519 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1528 Renderbuffer* GetRenderbufferInfoForTarget(
1530 Renderbuffer* renderbuffer = NULL;
1532 case GL_RENDERBUFFER:
1533 renderbuffer = state_.bound_renderbuffer.get();
1539 return renderbuffer;
1542 // Validates the program and location for a glGetUniform call and returns
1543 // a SizeResult setup to receive the result. Returns true if glGetUniform
1544 // should be called.
1545 bool GetUniformSetup(
1546 GLuint program, GLint fake_location,
1547 uint32 shm_id, uint32 shm_offset,
1548 error::Error* error, GLint* real_location, GLuint* service_id,
1549 void** result, GLenum* result_type);
1551 virtual bool WasContextLost() OVERRIDE;
1552 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1553 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1555 #if defined(OS_MACOSX)
1556 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1559 bool ValidateCompressedTexDimensions(
1560 const char* function_name,
1561 GLint level, GLsizei width, GLsizei height, GLenum format);
1562 bool ValidateCompressedTexFuncData(
1563 const char* function_name,
1564 GLsizei width, GLsizei height, GLenum format, size_t size);
1565 bool ValidateCompressedTexSubDimensions(
1566 const char* function_name,
1567 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1568 GLsizei width, GLsizei height, GLenum format,
1571 void RenderWarning(const char* filename, int line, const std::string& msg);
1572 void PerformanceWarning(
1573 const char* filename, int line, const std::string& msg);
1575 const FeatureInfo::FeatureFlags& features() const {
1576 return feature_info_->feature_flags();
1579 const FeatureInfo::Workarounds& workarounds() const {
1580 return feature_info_->workarounds();
1583 bool ShouldDeferDraws() {
1584 return !offscreen_target_frame_buffer_.get() &&
1585 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1586 surface_->DeferDraws();
1589 bool ShouldDeferReads() {
1590 return !offscreen_target_frame_buffer_.get() &&
1591 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1592 surface_->DeferDraws();
1595 error::Error WillAccessBoundFramebufferForDraw() {
1596 if (ShouldDeferDraws())
1597 return error::kDeferCommandUntilLater;
1598 if (!offscreen_target_frame_buffer_.get() &&
1599 !framebuffer_state_.bound_draw_framebuffer.get() &&
1600 !surface_->SetBackbufferAllocation(true))
1601 return error::kLostContext;
1602 return error::kNoError;
1605 error::Error WillAccessBoundFramebufferForRead() {
1606 if (ShouldDeferReads())
1607 return error::kDeferCommandUntilLater;
1608 if (!offscreen_target_frame_buffer_.get() &&
1609 !framebuffer_state_.bound_read_framebuffer.get() &&
1610 !surface_->SetBackbufferAllocation(true))
1611 return error::kLostContext;
1612 return error::kNoError;
1615 void ProcessPendingReadPixels();
1616 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1618 // Generate a member function prototype for each command in an automated and
1620 #define GLES2_CMD_OP(name) \
1621 Error Handle ## name( \
1622 uint32 immediate_data_size, \
1623 const cmds::name& args); \
1625 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1629 // The GL context this decoder renders to on behalf of the client.
1630 scoped_refptr<gfx::GLSurface> surface_;
1631 scoped_refptr<gfx::GLContext> context_;
1633 // The ContextGroup for this decoder uses to track resources.
1634 scoped_refptr<ContextGroup> group_;
1636 DebugMarkerManager debug_marker_manager_;
1639 // All the state for this context.
1640 ContextState state_;
1642 // Current width and height of the offscreen frame buffer.
1643 gfx::Size offscreen_size_;
1645 // Util to help with GL.
1648 // unpack flip y as last set by glPixelStorei
1649 bool unpack_flip_y_;
1651 // unpack (un)premultiply alpha as last set by glPixelStorei
1652 bool unpack_premultiply_alpha_;
1653 bool unpack_unpremultiply_alpha_;
1655 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1656 GLuint attrib_0_buffer_id_;
1658 // The value currently in attrib_0.
1659 Vec4 attrib_0_value_;
1661 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1662 bool attrib_0_buffer_matches_value_;
1664 // The size of attrib 0.
1665 GLsizei attrib_0_size_;
1667 // The buffer used to simulate GL_FIXED attribs.
1668 GLuint fixed_attrib_buffer_id_;
1670 // The size of fiixed attrib buffer.
1671 GLsizei fixed_attrib_buffer_size_;
1673 // The offscreen frame buffer that the client renders to. With EGL, the
1674 // depth and stencil buffers are separate. With regular GL there is a single
1675 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1676 // offscreen_target_stencil_render_buffer_ is unused.
1677 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1678 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1679 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1680 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1681 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1682 GLenum offscreen_target_color_format_;
1683 GLenum offscreen_target_depth_format_;
1684 GLenum offscreen_target_stencil_format_;
1685 GLsizei offscreen_target_samples_;
1686 GLboolean offscreen_target_buffer_preserved_;
1688 // The copy that is saved when SwapBuffers is called.
1689 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1690 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1691 scoped_refptr<TextureRef>
1692 offscreen_saved_color_texture_info_;
1694 // The copy that is used as the destination for multi-sample resolves.
1695 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1696 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1697 GLenum offscreen_saved_color_format_;
1699 scoped_ptr<QueryManager> query_manager_;
1701 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1703 base::Callback<void(gfx::Size, float)> resize_callback_;
1705 WaitSyncPointCallback wait_sync_point_callback_;
1707 ShaderCacheCallback shader_cache_callback_;
1709 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1711 // The format of the back buffer_
1712 GLenum back_buffer_color_format_;
1713 bool back_buffer_has_depth_;
1714 bool back_buffer_has_stencil_;
1716 // Backbuffer attachments that are currently undefined.
1717 uint32 backbuffer_needs_clear_bits_;
1719 // The current decoder error.
1720 error::Error current_decoder_error_;
1722 bool use_shader_translator_;
1723 scoped_refptr<ShaderTranslator> vertex_translator_;
1724 scoped_refptr<ShaderTranslator> fragment_translator_;
1726 DisallowedFeatures disallowed_features_;
1728 // Cached from ContextGroup
1729 const Validators* validators_;
1730 scoped_refptr<FeatureInfo> feature_info_;
1734 bool has_robustness_extension_;
1735 GLenum reset_status_;
1736 bool reset_by_robustness_extension_;
1737 bool supports_post_sub_buffer_;
1739 // These flags are used to override the state of the shared feature_info_
1740 // member. Because the same FeatureInfo instance may be shared among many
1741 // contexts, the assumptions on the availablity of extensions in WebGL
1742 // contexts may be broken. These flags override the shared state to preserve
1744 bool force_webgl_glsl_validation_;
1745 bool derivatives_explicitly_enabled_;
1746 bool frag_depth_explicitly_enabled_;
1747 bool draw_buffers_explicitly_enabled_;
1748 bool shader_texture_lod_explicitly_enabled_;
1750 bool compile_shader_always_succeeds_;
1752 // An optional behaviour to lose the context and group when OOM.
1753 bool lose_context_when_out_of_memory_;
1756 bool service_logging_;
1758 #if defined(OS_MACOSX)
1759 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1760 TextureToIOSurfaceMap texture_to_io_surface_map_;
1763 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1765 // Cached values of the currently assigned viewport dimensions.
1766 GLsizei viewport_max_width_;
1767 GLsizei viewport_max_height_;
1769 // Command buffer stats.
1770 base::TimeDelta total_processing_commands_time_;
1772 // States related to each manager.
1773 DecoderTextureState texture_state_;
1774 DecoderFramebufferState framebuffer_state_;
1776 scoped_ptr<GPUTracer> gpu_tracer_;
1777 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1778 int gpu_trace_level_;
1779 bool gpu_trace_commands_;
1781 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1783 // Used to validate multisample renderbuffers if needed
1784 GLuint validation_texture_;
1785 GLuint validation_fbo_multisample_;
1786 GLuint validation_fbo_;
1788 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1791 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1792 const char* function_name, ErrorState* error_state)
1793 : function_name_(function_name),
1794 error_state_(error_state) {
1795 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1798 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1799 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1802 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1803 TextureUnit& info = state->texture_units[0];
1805 scoped_refptr<TextureRef> texture_ref;
1808 texture_ref = info.bound_texture_2d;
1810 case GL_TEXTURE_CUBE_MAP:
1811 texture_ref = info.bound_texture_cube_map;
1813 case GL_TEXTURE_EXTERNAL_OES:
1814 texture_ref = info.bound_texture_external_oes;
1816 case GL_TEXTURE_RECTANGLE_ARB:
1817 texture_ref = info.bound_texture_rectangle_arb;
1823 if (texture_ref.get()) {
1824 last_id = texture_ref->service_id();
1829 glBindTexture(target, last_id);
1830 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1833 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1838 ScopedGLErrorSuppressor suppressor(
1839 "ScopedTextureBinder::ctor", state_->GetErrorState());
1841 // TODO(apatrick): Check if there are any other states that need to be reset
1842 // before binding a new texture.
1843 glActiveTexture(GL_TEXTURE0);
1844 glBindTexture(target, id);
1847 ScopedTextureBinder::~ScopedTextureBinder() {
1848 ScopedGLErrorSuppressor suppressor(
1849 "ScopedTextureBinder::dtor", state_->GetErrorState());
1850 RestoreCurrentTextureBindings(state_, target_);
1853 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1856 ScopedGLErrorSuppressor suppressor(
1857 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1858 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1861 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1862 ScopedGLErrorSuppressor suppressor(
1863 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1864 state_->RestoreRenderbufferBindings();
1867 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1869 : decoder_(decoder) {
1870 ScopedGLErrorSuppressor suppressor(
1871 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1872 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1873 decoder->OnFboChanged();
1876 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1877 ScopedGLErrorSuppressor suppressor(
1878 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1879 decoder_->RestoreCurrentFramebufferBindings();
1882 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1883 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1884 : decoder_(decoder) {
1885 resolve_and_bind_ = (
1886 decoder_->offscreen_target_frame_buffer_.get() &&
1887 decoder_->IsOffscreenBufferMultisampled() &&
1888 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1889 enforce_internal_framebuffer));
1890 if (!resolve_and_bind_)
1893 ScopedGLErrorSuppressor suppressor(
1894 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1895 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1896 decoder_->offscreen_target_frame_buffer_->id());
1899 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1900 decoder_->offscreen_resolved_frame_buffer_.reset(
1901 new BackFramebuffer(decoder_));
1902 decoder_->offscreen_resolved_frame_buffer_->Create();
1903 decoder_->offscreen_resolved_color_texture_.reset(
1904 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1905 decoder_->offscreen_resolved_color_texture_->Create();
1907 DCHECK(decoder_->offscreen_saved_color_format_);
1908 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1909 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1911 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1912 decoder_->offscreen_resolved_color_texture_.get());
1913 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1914 GL_FRAMEBUFFER_COMPLETE) {
1915 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1916 << "because offscreen resolved FBO was incomplete.";
1920 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1922 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1924 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1925 const int width = decoder_->offscreen_size_.width();
1926 const int height = decoder_->offscreen_size_.height();
1927 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
1928 decoder->BlitFramebufferHelper(0,
1936 GL_COLOR_BUFFER_BIT,
1938 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1941 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1942 if (!resolve_and_bind_)
1945 ScopedGLErrorSuppressor suppressor(
1946 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1947 decoder_->RestoreCurrentFramebufferBindings();
1948 if (decoder_->state_.enable_flags.scissor_test) {
1949 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
1953 BackTexture::BackTexture(
1954 MemoryTracker* memory_tracker,
1955 ContextState* state)
1956 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1958 bytes_allocated_(0),
1962 BackTexture::~BackTexture() {
1963 // This does not destroy the render texture because that would require that
1964 // the associated GL context was current. Just check that it was explicitly
1969 void BackTexture::Create() {
1970 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1971 state_->GetErrorState());
1973 glGenTextures(1, &id_);
1974 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1975 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1976 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1977 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1978 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1980 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1981 // never called on an offscreen context, no data will ever be uploaded to the
1982 // saved offscreen color texture (it is deferred until to when SwapBuffers
1983 // is called). My idea is that some nvidia drivers might have a bug where
1984 // deleting a texture that has never been populated might cause a
1987 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1989 bytes_allocated_ = 16u * 16u * 4u;
1990 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1993 bool BackTexture::AllocateStorage(
1994 const gfx::Size& size, GLenum format, bool zero) {
1996 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
1997 state_->GetErrorState());
1998 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1999 uint32 image_size = 0;
2000 GLES2Util::ComputeImageDataSizes(
2001 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
2004 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2008 scoped_ptr<char[]> zero_data;
2010 zero_data.reset(new char[image_size]);
2011 memset(zero_data.get(), 0, image_size);
2014 glTexImage2D(GL_TEXTURE_2D,
2026 bool success = glGetError() == GL_NO_ERROR;
2028 memory_tracker_.TrackMemFree(bytes_allocated_);
2029 bytes_allocated_ = image_size;
2030 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2035 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2037 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2038 state_->GetErrorState());
2039 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2040 glCopyTexImage2D(GL_TEXTURE_2D,
2049 void BackTexture::Destroy() {
2051 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2052 state_->GetErrorState());
2053 glDeleteTextures(1, &id_);
2056 memory_tracker_.TrackMemFree(bytes_allocated_);
2057 bytes_allocated_ = 0;
2060 void BackTexture::Invalidate() {
2064 BackRenderbuffer::BackRenderbuffer(
2065 RenderbufferManager* renderbuffer_manager,
2066 MemoryTracker* memory_tracker,
2067 ContextState* state)
2068 : renderbuffer_manager_(renderbuffer_manager),
2069 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2071 bytes_allocated_(0),
2075 BackRenderbuffer::~BackRenderbuffer() {
2076 // This does not destroy the render buffer because that would require that
2077 // the associated GL context was current. Just check that it was explicitly
2082 void BackRenderbuffer::Create() {
2083 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2084 state_->GetErrorState());
2086 glGenRenderbuffersEXT(1, &id_);
2089 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2090 const gfx::Size& size,
2093 ScopedGLErrorSuppressor suppressor(
2094 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2095 ScopedRenderBufferBinder binder(state_, id_);
2097 uint32 estimated_size = 0;
2098 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2099 size.width(), size.height(), samples, format, &estimated_size)) {
2103 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2108 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2113 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2120 bool success = glGetError() == GL_NO_ERROR;
2122 // Mark the previously allocated bytes as free.
2123 memory_tracker_.TrackMemFree(bytes_allocated_);
2124 bytes_allocated_ = estimated_size;
2125 // Track the newly allocated bytes.
2126 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2131 void BackRenderbuffer::Destroy() {
2133 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2134 state_->GetErrorState());
2135 glDeleteRenderbuffersEXT(1, &id_);
2138 memory_tracker_.TrackMemFree(bytes_allocated_);
2139 bytes_allocated_ = 0;
2142 void BackRenderbuffer::Invalidate() {
2146 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2147 : decoder_(decoder),
2151 BackFramebuffer::~BackFramebuffer() {
2152 // This does not destroy the frame buffer because that would require that
2153 // the associated GL context was current. Just check that it was explicitly
2158 void BackFramebuffer::Create() {
2159 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2160 decoder_->GetErrorState());
2162 glGenFramebuffersEXT(1, &id_);
2165 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2167 ScopedGLErrorSuppressor suppressor(
2168 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2169 ScopedFrameBufferBinder binder(decoder_, id_);
2170 GLuint attach_id = texture ? texture->id() : 0;
2171 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2172 GL_COLOR_ATTACHMENT0,
2178 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2179 BackRenderbuffer* render_buffer) {
2181 ScopedGLErrorSuppressor suppressor(
2182 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2183 ScopedFrameBufferBinder binder(decoder_, id_);
2184 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2185 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2191 void BackFramebuffer::Destroy() {
2193 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2194 decoder_->GetErrorState());
2195 glDeleteFramebuffersEXT(1, &id_);
2200 void BackFramebuffer::Invalidate() {
2204 GLenum BackFramebuffer::CheckStatus() {
2206 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2207 decoder_->GetErrorState());
2208 ScopedFrameBufferBinder binder(decoder_, id_);
2209 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2212 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2213 return new GLES2DecoderImpl(group);
2216 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2219 logger_(&debug_marker_manager_),
2220 state_(group_->feature_info(), this, &logger_),
2221 unpack_flip_y_(false),
2222 unpack_premultiply_alpha_(false),
2223 unpack_unpremultiply_alpha_(false),
2224 attrib_0_buffer_id_(0),
2225 attrib_0_buffer_matches_value_(true),
2227 fixed_attrib_buffer_id_(0),
2228 fixed_attrib_buffer_size_(0),
2229 offscreen_target_color_format_(0),
2230 offscreen_target_depth_format_(0),
2231 offscreen_target_stencil_format_(0),
2232 offscreen_target_samples_(0),
2233 offscreen_target_buffer_preserved_(true),
2234 offscreen_saved_color_format_(0),
2235 back_buffer_color_format_(0),
2236 back_buffer_has_depth_(false),
2237 back_buffer_has_stencil_(false),
2238 backbuffer_needs_clear_bits_(0),
2239 current_decoder_error_(error::kNoError),
2240 use_shader_translator_(true),
2241 validators_(group_->feature_info()->validators()),
2242 feature_info_(group_->feature_info()),
2244 has_robustness_extension_(false),
2245 reset_status_(GL_NO_ERROR),
2246 reset_by_robustness_extension_(false),
2247 supports_post_sub_buffer_(false),
2248 force_webgl_glsl_validation_(false),
2249 derivatives_explicitly_enabled_(false),
2250 frag_depth_explicitly_enabled_(false),
2251 draw_buffers_explicitly_enabled_(false),
2252 shader_texture_lod_explicitly_enabled_(false),
2253 compile_shader_always_succeeds_(false),
2254 lose_context_when_out_of_memory_(false),
2255 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2256 switches::kEnableGPUServiceLoggingGPU)),
2257 viewport_max_width_(0),
2258 viewport_max_height_(0),
2259 texture_state_(group_->feature_info()
2261 .texsubimage2d_faster_than_teximage2d),
2262 validation_texture_(0),
2263 validation_fbo_multisample_(0),
2264 validation_fbo_(0) {
2267 attrib_0_value_.v[0] = 0.0f;
2268 attrib_0_value_.v[1] = 0.0f;
2269 attrib_0_value_.v[2] = 0.0f;
2270 attrib_0_value_.v[3] = 1.0f;
2272 // The shader translator is used for WebGL even when running on EGL
2273 // because additional restrictions are needed (like only enabling
2274 // GL_OES_standard_derivatives on demand). It is used for the unit
2275 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2276 // the empty string to CompileShader and this is not a valid shader.
2277 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2278 CommandLine::ForCurrentProcess()->HasSwitch(
2279 switches::kDisableGLSLTranslator)) {
2280 use_shader_translator_ = false;
2284 GLES2DecoderImpl::~GLES2DecoderImpl() {
2287 bool GLES2DecoderImpl::Initialize(
2288 const scoped_refptr<gfx::GLSurface>& surface,
2289 const scoped_refptr<gfx::GLContext>& context,
2291 const gfx::Size& size,
2292 const DisallowedFeatures& disallowed_features,
2293 const std::vector<int32>& attribs) {
2294 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2295 DCHECK(context->IsCurrent(surface.get()));
2296 DCHECK(!context_.get());
2299 gpu_tracer_ = GPUTracer::Create(this);
2300 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2301 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2302 gpu_trace_level_ = 2;
2303 gpu_trace_commands_ = false;
2305 if (CommandLine::ForCurrentProcess()->HasSwitch(
2306 switches::kEnableGPUDebugging)) {
2310 if (CommandLine::ForCurrentProcess()->HasSwitch(
2311 switches::kEnableGPUCommandLogging)) {
2312 set_log_commands(true);
2315 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2316 switches::kCompileShaderAlwaysSucceeds);
2319 // Take ownership of the context and surface. The surface can be replaced with
2324 ContextCreationAttribHelper attrib_parser;
2325 if (!attrib_parser.Parse(attribs))
2328 // Save the loseContextWhenOutOfMemory context creation attribute.
2329 lose_context_when_out_of_memory_ =
2330 attrib_parser.lose_context_when_out_of_memory_;
2332 // If the failIfMajorPerformanceCaveat context creation attribute was true
2333 // and we are using a software renderer, fail.
2334 if (attrib_parser.fail_if_major_perf_caveat_ &&
2335 feature_info_->feature_flags().is_swiftshader) {
2336 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2341 if (!group_->Initialize(this, disallowed_features)) {
2342 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2343 << "failed to initialize.";
2344 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2350 disallowed_features_ = disallowed_features;
2352 state_.attrib_values.resize(group_->max_vertex_attribs());
2353 vertex_array_manager_.reset(new VertexArrayManager());
2355 GLuint default_vertex_attrib_service_id = 0;
2356 if (features().native_vertex_array_object) {
2357 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2358 glBindVertexArrayOES(default_vertex_attrib_service_id);
2361 state_.default_vertex_attrib_manager =
2362 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2364 state_.default_vertex_attrib_manager->Initialize(
2365 group_->max_vertex_attribs(),
2366 feature_info_->workarounds().init_vertex_attributes);
2368 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2369 DoBindVertexArrayOES(0);
2371 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2373 util_.set_num_compressed_texture_formats(
2374 validators_->compressed_texture_format.GetValues().size());
2376 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2377 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2378 // OpenGL ES 2.0 does not have this issue.
2379 glEnableVertexAttribArray(0);
2381 glGenBuffersARB(1, &attrib_0_buffer_id_);
2382 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2383 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2384 glBindBuffer(GL_ARRAY_BUFFER, 0);
2385 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2387 state_.texture_units.resize(group_->max_texture_units());
2388 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2389 glActiveTexture(GL_TEXTURE0 + tt);
2390 // We want the last bind to be 2D.
2392 if (features().oes_egl_image_external) {
2393 ref = texture_manager()->GetDefaultTextureInfo(
2394 GL_TEXTURE_EXTERNAL_OES);
2395 state_.texture_units[tt].bound_texture_external_oes = ref;
2396 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2398 if (features().arb_texture_rectangle) {
2399 ref = texture_manager()->GetDefaultTextureInfo(
2400 GL_TEXTURE_RECTANGLE_ARB);
2401 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2402 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2404 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2405 state_.texture_units[tt].bound_texture_cube_map = ref;
2406 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2407 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2408 state_.texture_units[tt].bound_texture_2d = ref;
2409 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2411 glActiveTexture(GL_TEXTURE0);
2415 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2416 features().chromium_framebuffer_multisample) {
2417 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2418 // max_sample_count must be initialized to a sane value. If
2419 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2420 GLint max_sample_count = 1;
2421 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2422 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2425 offscreen_target_samples_ = 1;
2427 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2429 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2430 const bool rgb8_supported =
2431 context_->HasExtension("GL_OES_rgb8_rgba8");
2432 // The only available default render buffer formats in GLES2 have very
2433 // little precision. Don't enable multisampling unless 8-bit render
2434 // buffer formats are available--instead fall back to 8-bit textures.
2435 if (rgb8_supported && offscreen_target_samples_ > 1) {
2436 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2439 offscreen_target_samples_ = 1;
2440 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2444 // ANGLE only supports packed depth/stencil formats, so use it if it is
2446 const bool depth24_stencil8_supported =
2447 feature_info_->feature_flags().packed_depth24_stencil8;
2448 VLOG(1) << "GL_OES_packed_depth_stencil "
2449 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2450 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2451 depth24_stencil8_supported) {
2452 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2453 offscreen_target_stencil_format_ = 0;
2455 // It may be the case that this depth/stencil combination is not
2456 // supported, but this will be checked later by CheckFramebufferStatus.
2457 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2458 GL_DEPTH_COMPONENT16 : 0;
2459 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2460 GL_STENCIL_INDEX8 : 0;
2463 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2466 // If depth is requested at all, use the packed depth stencil format if
2467 // it's available, as some desktop GL drivers don't support any non-packed
2468 // formats for depth attachments.
2469 const bool depth24_stencil8_supported =
2470 feature_info_->feature_flags().packed_depth24_stencil8;
2471 VLOG(1) << "GL_EXT_packed_depth_stencil "
2472 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2474 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2475 depth24_stencil8_supported) {
2476 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2477 offscreen_target_stencil_format_ = 0;
2479 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2480 GL_DEPTH_COMPONENT : 0;
2481 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2482 GL_STENCIL_INDEX : 0;
2486 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2489 // Create the target frame buffer. This is the one that the client renders
2491 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2492 offscreen_target_frame_buffer_->Create();
2493 // Due to GLES2 format limitations, either the color texture (for
2494 // non-multisampling) or the color render buffer (for multisampling) will be
2495 // attached to the offscreen frame buffer. The render buffer has more
2496 // limited formats available to it, but the texture can't do multisampling.
2497 if (IsOffscreenBufferMultisampled()) {
2498 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2499 renderbuffer_manager(), memory_tracker(), &state_));
2500 offscreen_target_color_render_buffer_->Create();
2502 offscreen_target_color_texture_.reset(new BackTexture(
2503 memory_tracker(), &state_));
2504 offscreen_target_color_texture_->Create();
2506 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2507 renderbuffer_manager(), memory_tracker(), &state_));
2508 offscreen_target_depth_render_buffer_->Create();
2509 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2510 renderbuffer_manager(), memory_tracker(), &state_));
2511 offscreen_target_stencil_render_buffer_->Create();
2513 // Create the saved offscreen texture. The target frame buffer is copied
2514 // here when SwapBuffers is called.
2515 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2516 offscreen_saved_frame_buffer_->Create();
2518 offscreen_saved_color_texture_.reset(new BackTexture(
2519 memory_tracker(), &state_));
2520 offscreen_saved_color_texture_->Create();
2522 // Allocate the render buffers at their initial size and check the status
2523 // of the frame buffers is okay.
2524 if (!ResizeOffscreenFrameBuffer(size)) {
2525 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2530 // Allocate the offscreen saved color texture.
2531 DCHECK(offscreen_saved_color_format_);
2532 offscreen_saved_color_texture_->AllocateStorage(
2533 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2535 offscreen_saved_frame_buffer_->AttachRenderTexture(
2536 offscreen_saved_color_texture_.get());
2537 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2538 GL_FRAMEBUFFER_COMPLETE) {
2539 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2544 // Bind to the new default frame buffer (the offscreen target frame buffer).
2545 // This should now be associated with ID zero.
2546 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2548 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2549 // These are NOT if the back buffer has these proprorties. They are
2550 // if we want the command buffer to enforce them regardless of what
2551 // the real backbuffer is assuming the real back buffer gives us more than
2552 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2553 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2554 // can't do anything about that.
2557 glGetIntegerv(GL_ALPHA_BITS, &v);
2558 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2559 // user requested RGB then RGB. If the user did not specify a preference
2560 // than use whatever we were given. Same for DEPTH and STENCIL.
2561 back_buffer_color_format_ =
2562 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2563 glGetIntegerv(GL_DEPTH_BITS, &v);
2564 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2565 glGetIntegerv(GL_STENCIL_BITS, &v);
2566 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2569 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2570 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2571 // isn't well documented; it was discovered in the Khronos OpenGL ES
2572 // mailing list archives. It also implicitly enables the desktop GL
2573 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2574 // variable in fragment shaders.
2575 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2576 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2577 glEnable(GL_POINT_SPRITE);
2580 has_robustness_extension_ =
2581 context->HasExtension("GL_ARB_robustness") ||
2582 context->HasExtension("GL_EXT_robustness");
2584 if (!InitializeShaderTranslator()) {
2588 state_.viewport_width = size.width();
2589 state_.viewport_height = size.height();
2591 GLint viewport_params[4] = { 0 };
2592 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2593 viewport_max_width_ = viewport_params[0];
2594 viewport_max_height_ = viewport_params[1];
2596 state_.scissor_width = state_.viewport_width;
2597 state_.scissor_height = state_.viewport_height;
2599 // Set all the default state because some GL drivers get it wrong.
2600 state_.InitCapabilities(NULL);
2601 state_.InitState(NULL);
2602 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2604 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2605 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2606 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2607 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2609 bool call_gl_clear = true;
2610 #if defined(OS_ANDROID)
2611 // Temporary workaround for Android WebView because this clear ignores the
2612 // clip and corrupts that external UI of the App. Not calling glClear is ok
2613 // because the system already clears the buffer before each draw. Proper
2614 // fix might be setting the scissor clip properly before initialize. See
2615 // crbug.com/259023 for details.
2616 call_gl_clear = surface_->GetHandle();
2618 if (call_gl_clear) {
2619 // Clear the backbuffer.
2620 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2623 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2624 if (feature_info_->workarounds()
2625 .disable_post_sub_buffers_for_onscreen_surfaces &&
2626 !surface->IsOffscreen())
2627 supports_post_sub_buffer_ = false;
2629 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2630 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2633 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2634 context_->SetUnbindFboOnMakeCurrent();
2637 if (feature_info_->workarounds().release_image_after_use) {
2638 image_manager()->SetReleaseAfterUse();
2641 // Only compositor contexts are known to use only the subset of GL
2642 // that can be safely migrated between the iGPU and the dGPU. Mark
2643 // those contexts as safe to forcibly transition between the GPUs.
2644 // http://crbug.com/180876, http://crbug.com/227228
2646 context_->SetSafeToForceGpuSwitch();
2648 async_pixel_transfer_manager_.reset(
2649 AsyncPixelTransferManager::Create(context.get()));
2650 async_pixel_transfer_manager_->Initialize(texture_manager());
2652 framebuffer_manager()->AddObserver(this);
2657 Capabilities GLES2DecoderImpl::GetCapabilities() {
2658 DCHECK(initialized());
2662 caps.fast_npot_mo8_textures =
2663 feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
2664 caps.egl_image_external =
2665 feature_info_->feature_flags().oes_egl_image_external;
2666 caps.texture_format_bgra8888 =
2667 feature_info_->feature_flags().ext_texture_format_bgra8888;
2668 caps.texture_format_etc1 =
2669 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2670 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2671 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2672 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2673 caps.discard_framebuffer =
2674 feature_info_->feature_flags().ext_discard_framebuffer;
2675 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2677 #if defined(OS_MACOSX)
2678 // This is unconditionally true on mac, no need to test for it at runtime.
2679 caps.iosurface = true;
2682 caps.post_sub_buffer = supports_post_sub_buffer_;
2683 caps.map_image = !!image_manager();
2688 void GLES2DecoderImpl::UpdateCapabilities() {
2689 util_.set_num_compressed_texture_formats(
2690 validators_->compressed_texture_format.GetValues().size());
2691 util_.set_num_shader_binary_formats(
2692 validators_->shader_binary_format.GetValues().size());
2695 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2696 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2698 if (!use_shader_translator_) {
2701 ShBuiltInResources resources;
2702 ShInitBuiltInResources(&resources);
2703 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2704 resources.MaxVertexUniformVectors =
2705 group_->max_vertex_uniform_vectors();
2706 resources.MaxVaryingVectors = group_->max_varying_vectors();
2707 resources.MaxVertexTextureImageUnits =
2708 group_->max_vertex_texture_image_units();
2709 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2710 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2711 resources.MaxFragmentUniformVectors =
2712 group_->max_fragment_uniform_vectors();
2713 resources.MaxDrawBuffers = group_->max_draw_buffers();
2714 resources.MaxExpressionComplexity = 256;
2715 resources.MaxCallStackDepth = 256;
2717 #if (ANGLE_SH_VERSION >= 110)
2718 GLint range[2] = { 0, 0 };
2719 GLint precision = 0;
2720 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2722 resources.FragmentPrecisionHigh =
2723 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2726 if (force_webgl_glsl_validation_) {
2727 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2728 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2729 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2730 if (!draw_buffers_explicitly_enabled_)
2731 resources.MaxDrawBuffers = 1;
2732 #if (ANGLE_SH_VERSION >= 123)
2733 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2736 resources.OES_standard_derivatives =
2737 features().oes_standard_derivatives ? 1 : 0;
2738 resources.ARB_texture_rectangle =
2739 features().arb_texture_rectangle ? 1 : 0;
2740 resources.OES_EGL_image_external =
2741 features().oes_egl_image_external ? 1 : 0;
2742 resources.EXT_draw_buffers =
2743 features().ext_draw_buffers ? 1 : 0;
2744 resources.EXT_frag_depth =
2745 features().ext_frag_depth ? 1 : 0;
2746 #if (ANGLE_SH_VERSION >= 123)
2747 resources.EXT_shader_texture_lod =
2748 features().ext_shader_texture_lod ? 1 : 0;
2752 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2754 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2755 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2756 resources.HashFunction = &CityHashForAngle;
2758 resources.HashFunction = &CityHash64;
2761 resources.HashFunction = NULL;
2762 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2763 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2764 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2765 int driver_bug_workarounds = 0;
2766 if (workarounds().needs_glsl_built_in_function_emulation)
2767 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2768 if (workarounds().init_gl_position_in_vertex_shader)
2769 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2770 if (workarounds().unfold_short_circuit_as_ternary_operation)
2771 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2772 if (workarounds().init_varyings_without_static_use)
2773 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2774 if (workarounds().unroll_for_loop_with_sampler_array_index)
2775 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2777 vertex_translator_ = shader_translator_cache()->GetTranslator(
2781 implementation_type,
2782 static_cast<ShCompileOptions>(driver_bug_workarounds));
2783 if (!vertex_translator_.get()) {
2784 LOG(ERROR) << "Could not initialize vertex shader translator.";
2789 fragment_translator_ = shader_translator_cache()->GetTranslator(
2793 implementation_type,
2794 static_cast<ShCompileOptions>(driver_bug_workarounds));
2795 if (!fragment_translator_.get()) {
2796 LOG(ERROR) << "Could not initialize fragment shader translator.";
2803 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2804 for (GLsizei ii = 0; ii < n; ++ii) {
2805 if (GetBuffer(client_ids[ii])) {
2809 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2810 glGenBuffersARB(n, service_ids.get());
2811 for (GLsizei ii = 0; ii < n; ++ii) {
2812 CreateBuffer(client_ids[ii], service_ids[ii]);
2817 bool GLES2DecoderImpl::GenFramebuffersHelper(
2818 GLsizei n, const GLuint* client_ids) {
2819 for (GLsizei ii = 0; ii < n; ++ii) {
2820 if (GetFramebuffer(client_ids[ii])) {
2824 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2825 glGenFramebuffersEXT(n, service_ids.get());
2826 for (GLsizei ii = 0; ii < n; ++ii) {
2827 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2832 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2833 GLsizei n, const GLuint* client_ids) {
2834 for (GLsizei ii = 0; ii < n; ++ii) {
2835 if (GetRenderbuffer(client_ids[ii])) {
2839 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2840 glGenRenderbuffersEXT(n, service_ids.get());
2841 for (GLsizei ii = 0; ii < n; ++ii) {
2842 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2847 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2848 for (GLsizei ii = 0; ii < n; ++ii) {
2849 if (GetTexture(client_ids[ii])) {
2853 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2854 glGenTextures(n, service_ids.get());
2855 for (GLsizei ii = 0; ii < n; ++ii) {
2856 CreateTexture(client_ids[ii], service_ids[ii]);
2861 void GLES2DecoderImpl::DeleteBuffersHelper(
2862 GLsizei n, const GLuint* client_ids) {
2863 for (GLsizei ii = 0; ii < n; ++ii) {
2864 Buffer* buffer = GetBuffer(client_ids[ii]);
2865 if (buffer && !buffer->IsDeleted()) {
2866 state_.vertex_attrib_manager->Unbind(buffer);
2867 if (state_.bound_array_buffer.get() == buffer) {
2868 state_.bound_array_buffer = NULL;
2870 RemoveBuffer(client_ids[ii]);
2875 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2876 GLsizei n, const GLuint* client_ids) {
2877 bool supports_separate_framebuffer_binds =
2878 features().chromium_framebuffer_multisample;
2880 for (GLsizei ii = 0; ii < n; ++ii) {
2881 Framebuffer* framebuffer =
2882 GetFramebuffer(client_ids[ii]);
2883 if (framebuffer && !framebuffer->IsDeleted()) {
2884 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2885 framebuffer_state_.bound_draw_framebuffer = NULL;
2886 framebuffer_state_.clear_state_dirty = true;
2887 GLenum target = supports_separate_framebuffer_binds ?
2888 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2889 glBindFramebufferEXT(target, GetBackbufferServiceId());
2891 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2892 framebuffer_state_.bound_read_framebuffer = NULL;
2893 GLenum target = supports_separate_framebuffer_binds ?
2894 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2895 glBindFramebufferEXT(target, GetBackbufferServiceId());
2898 RemoveFramebuffer(client_ids[ii]);
2903 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2904 GLsizei n, const GLuint* client_ids) {
2905 bool supports_separate_framebuffer_binds =
2906 features().chromium_framebuffer_multisample;
2907 for (GLsizei ii = 0; ii < n; ++ii) {
2908 Renderbuffer* renderbuffer =
2909 GetRenderbuffer(client_ids[ii]);
2910 if (renderbuffer && !renderbuffer->IsDeleted()) {
2911 if (state_.bound_renderbuffer.get() == renderbuffer) {
2912 state_.bound_renderbuffer = NULL;
2914 // Unbind from current framebuffers.
2915 if (supports_separate_framebuffer_binds) {
2916 if (framebuffer_state_.bound_read_framebuffer.get()) {
2917 framebuffer_state_.bound_read_framebuffer
2918 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2920 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2921 framebuffer_state_.bound_draw_framebuffer
2922 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2925 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2926 framebuffer_state_.bound_draw_framebuffer
2927 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2930 framebuffer_state_.clear_state_dirty = true;
2931 RemoveRenderbuffer(client_ids[ii]);
2936 void GLES2DecoderImpl::DeleteTexturesHelper(
2937 GLsizei n, const GLuint* client_ids) {
2938 bool supports_separate_framebuffer_binds =
2939 features().chromium_framebuffer_multisample;
2940 for (GLsizei ii = 0; ii < n; ++ii) {
2941 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2943 Texture* texture = texture_ref->texture();
2944 if (texture->IsAttachedToFramebuffer()) {
2945 framebuffer_state_.clear_state_dirty = true;
2947 // Unbind texture_ref from texture_ref units.
2948 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2949 state_.texture_units[jj].Unbind(texture_ref);
2951 // Unbind from current framebuffers.
2952 if (supports_separate_framebuffer_binds) {
2953 if (framebuffer_state_.bound_read_framebuffer.get()) {
2954 framebuffer_state_.bound_read_framebuffer
2955 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2957 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2958 framebuffer_state_.bound_draw_framebuffer
2959 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2962 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2963 framebuffer_state_.bound_draw_framebuffer
2964 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2967 #if defined(OS_MACOSX)
2968 GLuint service_id = texture->service_id();
2969 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2970 ReleaseIOSurfaceForTexture(service_id);
2973 RemoveTexture(client_ids[ii]);
2978 // } // anonymous namespace
2980 bool GLES2DecoderImpl::MakeCurrent() {
2981 if (!context_.get())
2984 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
2985 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2987 // Some D3D drivers cannot recover from device lost in the GPU process
2988 // sandbox. Allow a new GPU process to launch.
2989 if (workarounds().exit_on_context_lost) {
2990 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2991 << " a D3D device in the Chrome GPU process sandbox.";
2993 base::win::SetShouldCrashOnProcessDetach(false);
3001 ProcessFinishedAsyncTransfers();
3003 // Rebind the FBO if it was unbound by the context.
3004 if (workarounds().unbind_fbo_on_context_switch)
3005 RestoreFramebufferBindings();
3007 framebuffer_state_.clear_state_dirty = true;
3012 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3013 ProcessPendingReadPixels();
3014 if (engine() && query_manager_.get())
3015 query_manager_->ProcessPendingTransferQueries();
3017 // TODO(epenner): Is there a better place to do this?
3018 // This needs to occur before we execute any batch of commands
3019 // from the client, as the client may have recieved an async
3020 // completion while issuing those commands.
3021 // "DidFlushStart" would be ideal if we had such a callback.
3022 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3025 static void RebindCurrentFramebuffer(
3027 Framebuffer* framebuffer,
3028 GLuint back_buffer_service_id) {
3029 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3031 if (framebuffer_id == 0) {
3032 framebuffer_id = back_buffer_service_id;
3035 glBindFramebufferEXT(target, framebuffer_id);
3038 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3039 framebuffer_state_.clear_state_dirty = true;
3041 if (!features().chromium_framebuffer_multisample) {
3042 RebindCurrentFramebuffer(
3044 framebuffer_state_.bound_draw_framebuffer.get(),
3045 GetBackbufferServiceId());
3047 RebindCurrentFramebuffer(
3048 GL_READ_FRAMEBUFFER_EXT,
3049 framebuffer_state_.bound_read_framebuffer.get(),
3050 GetBackbufferServiceId());
3051 RebindCurrentFramebuffer(
3052 GL_DRAW_FRAMEBUFFER_EXT,
3053 framebuffer_state_.bound_draw_framebuffer.get(),
3054 GetBackbufferServiceId());
3059 bool GLES2DecoderImpl::CheckFramebufferValid(
3060 Framebuffer* framebuffer,
3061 GLenum target, const char* func_name) {
3063 if (backbuffer_needs_clear_bits_) {
3064 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3065 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3066 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3070 state_.SetDeviceDepthMask(GL_TRUE);
3071 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3072 glClear(backbuffer_needs_clear_bits_);
3073 backbuffer_needs_clear_bits_ = 0;
3074 RestoreClearState();
3079 if (framebuffer_manager()->IsComplete(framebuffer)) {
3083 GLenum completeness = framebuffer->IsPossiblyComplete();
3084 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3086 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3090 // Are all the attachments cleared?
3091 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3092 texture_manager()->HaveUnclearedMips()) {
3093 if (!framebuffer->IsCleared()) {
3094 // Can we clear them?
3095 if (framebuffer->GetStatus(texture_manager(), target) !=
3096 GL_FRAMEBUFFER_COMPLETE) {
3098 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3099 "framebuffer incomplete (clear)");
3102 ClearUnclearedAttachments(target, framebuffer);
3106 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3107 if (framebuffer->GetStatus(texture_manager(), target) !=
3108 GL_FRAMEBUFFER_COMPLETE) {
3110 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3111 "framebuffer incomplete (check)");
3114 framebuffer_manager()->MarkAsComplete(framebuffer);
3117 // NOTE: At this point we don't know if the framebuffer is complete but
3118 // we DO know that everything that needs to be cleared has been cleared.
3122 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3123 if (!features().chromium_framebuffer_multisample) {
3124 bool valid = CheckFramebufferValid(
3125 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3133 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3134 GL_DRAW_FRAMEBUFFER_EXT,
3136 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3137 GL_READ_FRAMEBUFFER_EXT,
3141 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3142 Framebuffer* framebuffer =
3143 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3144 if (framebuffer != NULL) {
3145 const Framebuffer::Attachment* attachment =
3146 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3148 return gfx::Size(attachment->width(), attachment->height());
3150 return gfx::Size(0, 0);
3151 } else if (offscreen_target_frame_buffer_.get()) {
3152 return offscreen_size_;
3154 return surface_->GetSize();
3158 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3159 Framebuffer* framebuffer =
3160 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3161 if (framebuffer != NULL) {
3162 return framebuffer->GetColorAttachmentTextureType();
3164 return GL_UNSIGNED_BYTE;
3168 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3169 Framebuffer* framebuffer =
3170 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3171 if (framebuffer != NULL) {
3172 return framebuffer->GetColorAttachmentFormat();
3173 } else if (offscreen_target_frame_buffer_.get()) {
3174 return offscreen_target_color_format_;
3176 return back_buffer_color_format_;
3180 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3181 Framebuffer* framebuffer =
3182 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3183 if (framebuffer != NULL) {
3184 return framebuffer->GetColorAttachmentFormat();
3185 } else if (offscreen_target_frame_buffer_.get()) {
3186 return offscreen_target_color_format_;
3188 return back_buffer_color_format_;
3192 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3193 if (!offscreen_saved_color_texture_info_.get())
3195 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3196 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3197 texture_manager()->SetLevelInfo(
3198 offscreen_saved_color_texture_info_.get(),
3202 offscreen_size_.width(),
3203 offscreen_size_.height(),
3209 texture_manager()->SetParameteri(
3210 "UpdateParentTextureInfo",
3212 offscreen_saved_color_texture_info_.get(),
3213 GL_TEXTURE_MAG_FILTER,
3215 texture_manager()->SetParameteri(
3216 "UpdateParentTextureInfo",
3218 offscreen_saved_color_texture_info_.get(),
3219 GL_TEXTURE_MIN_FILTER,
3221 texture_manager()->SetParameteri(
3222 "UpdateParentTextureInfo",
3224 offscreen_saved_color_texture_info_.get(),
3227 texture_manager()->SetParameteri(
3228 "UpdateParentTextureInfo",
3230 offscreen_saved_color_texture_info_.get(),
3233 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3235 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3238 void GLES2DecoderImpl::SetResizeCallback(
3239 const base::Callback<void(gfx::Size, float)>& callback) {
3240 resize_callback_ = callback;
3243 Logger* GLES2DecoderImpl::GetLogger() {
3247 void GLES2DecoderImpl::BeginDecoding() {
3248 gpu_tracer_->BeginDecoding();
3249 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3252 void GLES2DecoderImpl::EndDecoding() {
3253 gpu_tracer_->EndDecoding();
3256 ErrorState* GLES2DecoderImpl::GetErrorState() {
3257 return state_.GetErrorState();
3260 void GLES2DecoderImpl::SetShaderCacheCallback(
3261 const ShaderCacheCallback& callback) {
3262 shader_cache_callback_ = callback;
3265 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3266 const WaitSyncPointCallback& callback) {
3267 wait_sync_point_callback_ = callback;
3270 AsyncPixelTransferManager*
3271 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3272 return async_pixel_transfer_manager_.get();
3275 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3276 async_pixel_transfer_manager_.reset();
3279 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3280 AsyncPixelTransferManager* manager) {
3281 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3284 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3285 uint32* service_texture_id) {
3286 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3288 *service_texture_id = texture_ref->service_id();
3294 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3295 return texture_state_.texture_upload_count +
3296 async_pixel_transfer_manager_->GetTextureUploadCount();
3299 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3300 return texture_state_.total_texture_upload_time +
3301 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3304 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3305 return total_processing_commands_time_;
3308 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3309 total_processing_commands_time_ += time;
3312 void GLES2DecoderImpl::Destroy(bool have_context) {
3316 DCHECK(!have_context || context_->IsCurrent(NULL));
3318 // Unbind everything.
3319 state_.vertex_attrib_manager = NULL;
3320 state_.default_vertex_attrib_manager = NULL;
3321 state_.texture_units.clear();
3322 state_.bound_array_buffer = NULL;
3323 state_.current_queries.clear();
3324 framebuffer_state_.bound_read_framebuffer = NULL;
3325 framebuffer_state_.bound_draw_framebuffer = NULL;
3326 state_.bound_renderbuffer = NULL;
3328 if (offscreen_saved_color_texture_info_.get()) {
3329 DCHECK(offscreen_target_color_texture_);
3330 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3331 offscreen_saved_color_texture_->id());
3332 offscreen_saved_color_texture_->Invalidate();
3333 offscreen_saved_color_texture_info_ = NULL;
3336 if (copy_texture_CHROMIUM_.get()) {
3337 copy_texture_CHROMIUM_->Destroy();
3338 copy_texture_CHROMIUM_.reset();
3341 if (state_.current_program.get()) {
3342 program_manager()->UnuseProgram(shader_manager(),
3343 state_.current_program.get());
3346 if (attrib_0_buffer_id_) {
3347 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3349 if (fixed_attrib_buffer_id_) {
3350 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3353 if (validation_texture_) {
3354 glDeleteTextures(1, &validation_texture_);
3355 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3356 glDeleteFramebuffersEXT(1, &validation_fbo_);
3359 if (offscreen_target_frame_buffer_.get())
3360 offscreen_target_frame_buffer_->Destroy();
3361 if (offscreen_target_color_texture_.get())
3362 offscreen_target_color_texture_->Destroy();
3363 if (offscreen_target_color_render_buffer_.get())
3364 offscreen_target_color_render_buffer_->Destroy();
3365 if (offscreen_target_depth_render_buffer_.get())
3366 offscreen_target_depth_render_buffer_->Destroy();
3367 if (offscreen_target_stencil_render_buffer_.get())
3368 offscreen_target_stencil_render_buffer_->Destroy();
3369 if (offscreen_saved_frame_buffer_.get())
3370 offscreen_saved_frame_buffer_->Destroy();
3371 if (offscreen_saved_color_texture_.get())
3372 offscreen_saved_color_texture_->Destroy();
3373 if (offscreen_resolved_frame_buffer_.get())
3374 offscreen_resolved_frame_buffer_->Destroy();
3375 if (offscreen_resolved_color_texture_.get())
3376 offscreen_resolved_color_texture_->Destroy();
3378 if (offscreen_target_frame_buffer_.get())
3379 offscreen_target_frame_buffer_->Invalidate();
3380 if (offscreen_target_color_texture_.get())
3381 offscreen_target_color_texture_->Invalidate();
3382 if (offscreen_target_color_render_buffer_.get())
3383 offscreen_target_color_render_buffer_->Invalidate();
3384 if (offscreen_target_depth_render_buffer_.get())
3385 offscreen_target_depth_render_buffer_->Invalidate();
3386 if (offscreen_target_stencil_render_buffer_.get())
3387 offscreen_target_stencil_render_buffer_->Invalidate();
3388 if (offscreen_saved_frame_buffer_.get())
3389 offscreen_saved_frame_buffer_->Invalidate();
3390 if (offscreen_saved_color_texture_.get())
3391 offscreen_saved_color_texture_->Invalidate();
3392 if (offscreen_resolved_frame_buffer_.get())
3393 offscreen_resolved_frame_buffer_->Invalidate();
3394 if (offscreen_resolved_color_texture_.get())
3395 offscreen_resolved_color_texture_->Invalidate();
3398 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3399 // Otherwise, we can leak objects. http://crbug.com/258772.
3400 // state_.current_program must be reset before group_ is reset because
3401 // the later deletes the ProgramManager object that referred by
3402 // state_.current_program object.
3403 state_.current_program = NULL;
3405 copy_texture_CHROMIUM_.reset();
3407 if (query_manager_.get()) {
3408 query_manager_->Destroy(have_context);
3409 query_manager_.reset();
3412 if (vertex_array_manager_ .get()) {
3413 vertex_array_manager_->Destroy(have_context);
3414 vertex_array_manager_.reset();
3417 offscreen_target_frame_buffer_.reset();
3418 offscreen_target_color_texture_.reset();
3419 offscreen_target_color_render_buffer_.reset();
3420 offscreen_target_depth_render_buffer_.reset();
3421 offscreen_target_stencil_render_buffer_.reset();
3422 offscreen_saved_frame_buffer_.reset();
3423 offscreen_saved_color_texture_.reset();
3424 offscreen_resolved_frame_buffer_.reset();
3425 offscreen_resolved_color_texture_.reset();
3427 // Need to release these before releasing |group_| which may own the
3428 // ShaderTranslatorCache.
3429 fragment_translator_ = NULL;
3430 vertex_translator_ = NULL;
3432 // Should destroy the transfer manager before the texture manager held
3433 // by the context group.
3434 async_pixel_transfer_manager_.reset();
3437 framebuffer_manager()->RemoveObserver(this);
3438 group_->Destroy(this, have_context);
3442 if (context_.get()) {
3443 context_->ReleaseCurrent(NULL);
3447 #if defined(OS_MACOSX)
3448 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3449 it != texture_to_io_surface_map_.end(); ++it) {
3450 CFRelease(it->second);
3452 texture_to_io_surface_map_.clear();
3456 void GLES2DecoderImpl::SetSurface(
3457 const scoped_refptr<gfx::GLSurface>& surface) {
3458 DCHECK(context_->IsCurrent(NULL));
3459 DCHECK(surface_.get());
3461 RestoreCurrentFramebufferBindings();
3464 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3465 if (!offscreen_saved_color_texture_.get()) {
3466 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3469 if (!offscreen_saved_color_texture_info_.get()) {
3470 GLuint service_id = offscreen_saved_color_texture_->id();
3471 offscreen_saved_color_texture_info_ = TextureRef::Create(
3472 texture_manager(), 0, service_id);
3473 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3475 UpdateParentTextureInfo();
3477 mailbox_manager()->ProduceTexture(
3478 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3481 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3482 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3483 if (!is_offscreen) {
3484 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3485 << " with an onscreen framebuffer.";
3489 if (offscreen_size_ == size)
3492 offscreen_size_ = size;
3493 int w = offscreen_size_.width();
3494 int h = offscreen_size_.height();
3495 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3496 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3497 << "to allocate storage due to excessive dimensions.";
3501 // Reallocate the offscreen target buffers.
3502 DCHECK(offscreen_target_color_format_);
3503 if (IsOffscreenBufferMultisampled()) {
3504 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3505 feature_info_, offscreen_size_, offscreen_target_color_format_,
3506 offscreen_target_samples_)) {
3507 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3508 << "to allocate storage for offscreen target color buffer.";
3512 if (!offscreen_target_color_texture_->AllocateStorage(
3513 offscreen_size_, offscreen_target_color_format_, false)) {
3514 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3515 << "to allocate storage for offscreen target color texture.";
3519 if (offscreen_target_depth_format_ &&
3520 !offscreen_target_depth_render_buffer_->AllocateStorage(
3521 feature_info_, offscreen_size_, offscreen_target_depth_format_,
3522 offscreen_target_samples_)) {
3523 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3524 << "to allocate storage for offscreen target depth buffer.";
3527 if (offscreen_target_stencil_format_ &&
3528 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3529 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
3530 offscreen_target_samples_)) {
3531 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3532 << "to allocate storage for offscreen target stencil buffer.";
3536 // Attach the offscreen target buffers to the target frame buffer.
3537 if (IsOffscreenBufferMultisampled()) {
3538 offscreen_target_frame_buffer_->AttachRenderBuffer(
3539 GL_COLOR_ATTACHMENT0,
3540 offscreen_target_color_render_buffer_.get());
3542 offscreen_target_frame_buffer_->AttachRenderTexture(
3543 offscreen_target_color_texture_.get());
3545 if (offscreen_target_depth_format_) {
3546 offscreen_target_frame_buffer_->AttachRenderBuffer(
3547 GL_DEPTH_ATTACHMENT,
3548 offscreen_target_depth_render_buffer_.get());
3550 const bool packed_depth_stencil =
3551 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3552 if (packed_depth_stencil) {
3553 offscreen_target_frame_buffer_->AttachRenderBuffer(
3554 GL_STENCIL_ATTACHMENT,
3555 offscreen_target_depth_render_buffer_.get());
3556 } else if (offscreen_target_stencil_format_) {
3557 offscreen_target_frame_buffer_->AttachRenderBuffer(
3558 GL_STENCIL_ATTACHMENT,
3559 offscreen_target_stencil_render_buffer_.get());
3562 if (offscreen_target_frame_buffer_->CheckStatus() !=
3563 GL_FRAMEBUFFER_COMPLETE) {
3564 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3565 << "because offscreen FBO was incomplete.";
3569 // Clear the target frame buffer.
3571 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3572 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3573 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3574 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3576 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
3577 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
3579 state_.SetDeviceDepthMask(GL_TRUE);
3580 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3581 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3582 RestoreClearState();
3585 // Destroy the offscreen resolved framebuffers.
3586 if (offscreen_resolved_frame_buffer_.get())
3587 offscreen_resolved_frame_buffer_->Destroy();
3588 if (offscreen_resolved_color_texture_.get())
3589 offscreen_resolved_color_texture_->Destroy();
3590 offscreen_resolved_color_texture_.reset();
3591 offscreen_resolved_frame_buffer_.reset();
3596 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3597 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3598 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3599 return error::kDeferCommandUntilLater;
3601 GLuint width = static_cast<GLuint>(c.width);
3602 GLuint height = static_cast<GLuint>(c.height);
3603 GLfloat scale_factor = c.scale_factor;
3604 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3606 width = std::max(1U, width);
3607 height = std::max(1U, height);
3609 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3610 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3611 // Make sure that we are done drawing to the back buffer before resizing.
3614 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3616 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3617 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3618 << "ResizeOffscreenFrameBuffer failed.";
3619 return error::kLostContext;
3623 if (!resize_callback_.is_null()) {
3624 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3625 DCHECK(context_->IsCurrent(surface_.get()));
3626 if (!context_->IsCurrent(surface_.get())) {
3627 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3628 << "current after resize callback.";
3629 return error::kLostContext;
3633 return error::kNoError;
3636 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3637 if (command_id > kStartPoint && command_id < kNumCommands) {
3638 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3640 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3643 // Decode command with its arguments, and call the corresponding GL function.
3644 // Note: args is a pointer to the command buffer. As such, it could be changed
3645 // by a (malicious) client at any time, so if validation has to happen, it
3646 // should operate on a copy of them.
3647 error::Error GLES2DecoderImpl::DoCommand(
3648 unsigned int command,
3649 unsigned int arg_count,
3650 const void* cmd_data) {
3651 error::Error result = error::kNoError;
3652 if (log_commands()) {
3653 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3654 // VLOG(1), no luck.
3655 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3656 << GetCommandName(command);
3658 unsigned int command_index = command - kStartPoint - 1;
3659 if (command_index < arraysize(g_command_info)) {
3660 const CommandInfo& info = g_command_info[command_index];
3661 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3662 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3663 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3664 bool doing_gpu_trace = false;
3665 if (gpu_trace_commands_) {
3666 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3667 doing_gpu_trace = true;
3668 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3672 uint32 immediate_data_size =
3673 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3675 #define GLES2_CMD_OP(name) \
3676 case cmds::name::kCmdId: \
3677 result = Handle ## name( \
3678 immediate_data_size, \
3679 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3682 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3686 if (doing_gpu_trace)
3687 gpu_tracer_->End(kTraceDecoder);
3691 while ((error = glGetError()) != GL_NO_ERROR) {
3692 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3693 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3694 << GetCommandName(command);
3695 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3699 result = error::kInvalidArguments;
3702 result = DoCommonCommand(command, arg_count, cmd_data);
3704 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3705 result = current_decoder_error_;
3706 current_decoder_error_ = error::kNoError;
3711 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3712 buffer_manager()->RemoveBuffer(client_id);
3715 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3716 if (GetProgram(client_id)) {
3719 GLuint service_id = glCreateProgram();
3720 if (service_id != 0) {
3721 CreateProgram(client_id, service_id);
3726 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3727 if (GetShader(client_id)) {
3730 GLuint service_id = glCreateShader(type);
3731 if (service_id != 0) {
3732 CreateShader(client_id, service_id, type);
3737 void GLES2DecoderImpl::DoFinish() {
3739 ProcessPendingReadPixels();
3740 ProcessPendingQueries();
3743 void GLES2DecoderImpl::DoFlush() {
3745 ProcessPendingQueries();
3748 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3749 GLuint texture_index = texture_unit - GL_TEXTURE0;
3750 if (texture_index >= state_.texture_units.size()) {
3751 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3752 "glActiveTexture", texture_unit, "texture_unit");
3755 state_.active_texture_unit = texture_index;
3756 glActiveTexture(texture_unit);
3759 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3760 Buffer* buffer = NULL;
3761 GLuint service_id = 0;
3762 if (client_id != 0) {
3763 buffer = GetBuffer(client_id);
3765 if (!group_->bind_generates_resource()) {
3766 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3768 "id not generated by glGenBuffers");
3772 // It's a new id so make a buffer buffer for it.
3773 glGenBuffersARB(1, &service_id);
3774 CreateBuffer(client_id, service_id);
3775 buffer = GetBuffer(client_id);
3776 IdAllocatorInterface* id_allocator =
3777 group_->GetIdAllocator(id_namespaces::kBuffers);
3778 id_allocator->MarkAsUsed(client_id);
3781 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3783 if (!buffer_manager()->SetTarget(buffer, target)) {
3785 GL_INVALID_OPERATION,
3786 "glBindBuffer", "buffer bound to more than 1 target");
3789 service_id = buffer->service_id();
3792 case GL_ARRAY_BUFFER:
3793 state_.bound_array_buffer = buffer;
3795 case GL_ELEMENT_ARRAY_BUFFER:
3796 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3799 NOTREACHED(); // Validation should prevent us getting here.
3802 glBindBuffer(target, service_id);
3805 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3806 bool all_draw_buffers) {
3807 Framebuffer* framebuffer =
3808 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3809 if (!all_draw_buffers || !framebuffer) {
3810 return (GLES2Util::GetChannelsForFormat(
3811 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3813 return framebuffer->HasAlphaMRT();
3816 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3817 Framebuffer* framebuffer =
3818 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3820 return framebuffer->HasDepthAttachment();
3822 if (offscreen_target_frame_buffer_.get()) {
3823 return offscreen_target_depth_format_ != 0;
3825 return back_buffer_has_depth_;
3828 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3829 Framebuffer* framebuffer =
3830 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3832 return framebuffer->HasStencilAttachment();
3834 if (offscreen_target_frame_buffer_.get()) {
3835 return offscreen_target_stencil_format_ != 0 ||
3836 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3838 return back_buffer_has_stencil_;
3841 void GLES2DecoderImpl::ApplyDirtyState() {
3842 if (framebuffer_state_.clear_state_dirty) {
3843 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
3844 state_.SetDeviceColorMask(state_.color_mask_red,
3845 state_.color_mask_green,
3846 state_.color_mask_blue,
3847 state_.color_mask_alpha && have_alpha);
3849 bool have_depth = BoundFramebufferHasDepthAttachment();
3850 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
3852 bool have_stencil = BoundFramebufferHasStencilAttachment();
3853 state_.SetDeviceStencilMaskSeparate(
3854 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3855 state_.SetDeviceStencilMaskSeparate(
3856 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3858 state_.SetDeviceCapabilityState(
3859 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3860 state_.SetDeviceCapabilityState(
3861 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3862 framebuffer_state_.clear_state_dirty = false;
3866 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3867 return (offscreen_target_frame_buffer_.get())
3868 ? offscreen_target_frame_buffer_->id()
3869 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3872 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) const {
3873 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3874 "context", logger_.GetLogPrefix());
3875 // Restore the Framebuffer first because of bugs in Intel drivers.
3876 // Intel drivers incorrectly clip the viewport settings to
3877 // the size of the current framebuffer object.
3878 RestoreFramebufferBindings();
3879 state_.RestoreState(prev_state);
3882 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3884 framebuffer_state_.bound_draw_framebuffer.get()
3885 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3886 : GetBackbufferServiceId();
3887 if (!features().chromium_framebuffer_multisample) {
3888 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3890 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3891 service_id = framebuffer_state_.bound_read_framebuffer.get()
3892 ? framebuffer_state_.bound_read_framebuffer->service_id()
3893 : GetBackbufferServiceId();
3894 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3899 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3900 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3902 GLenum target = texture->target();
3903 glBindTexture(target, service_id);
3905 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3907 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3909 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3911 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3912 RestoreTextureUnitBindings(state_.active_texture_unit);
3916 void GLES2DecoderImpl::ClearAllAttributes() const {
3917 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
3919 if (feature_info_->feature_flags().native_vertex_array_object)
3920 glBindVertexArrayOES(0);
3922 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
3923 if (i != 0) // Never disable attribute 0
3924 glDisableVertexAttribArray(i);
3925 if(features().angle_instanced_arrays)
3926 glVertexAttribDivisorANGLE(i, 0);
3930 void GLES2DecoderImpl::RestoreAllAttributes() const {
3931 state_.RestoreVertexAttribs();
3934 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
3935 state_.SetIgnoreCachedStateForTest(ignore);
3938 void GLES2DecoderImpl::OnFboChanged() const {
3939 if (workarounds().restore_scissor_on_fbo_change)
3940 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3943 // Called after the FBO is checked for completeness.
3944 void GLES2DecoderImpl::OnUseFramebuffer() const {
3945 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3946 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3947 // The driver forgets the correct scissor when modifying the FBO binding.
3948 glScissor(state_.scissor_x,
3950 state_.scissor_width,
3951 state_.scissor_height);
3953 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3954 // it's unclear how this bug works.
3959 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3960 Framebuffer* framebuffer = NULL;
3961 GLuint service_id = 0;
3962 if (client_id != 0) {
3963 framebuffer = GetFramebuffer(client_id);
3965 if (!group_->bind_generates_resource()) {
3966 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3967 "glBindFramebuffer",
3968 "id not generated by glGenFramebuffers");
3972 // It's a new id so make a framebuffer framebuffer for it.
3973 glGenFramebuffersEXT(1, &service_id);
3974 CreateFramebuffer(client_id, service_id);
3975 framebuffer = GetFramebuffer(client_id);
3976 IdAllocatorInterface* id_allocator =
3977 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3978 id_allocator->MarkAsUsed(client_id);
3980 service_id = framebuffer->service_id();
3982 framebuffer->MarkAsValid();
3984 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
3986 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3987 framebuffer_state_.bound_draw_framebuffer = framebuffer;
3990 // vmiura: This looks like dup code
3991 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3992 framebuffer_state_.bound_read_framebuffer = framebuffer;
3995 framebuffer_state_.clear_state_dirty = true;
3997 // If we are rendering to the backbuffer get the FBO id for any simulated
3999 if (framebuffer == NULL) {
4000 service_id = GetBackbufferServiceId();
4003 glBindFramebufferEXT(target, service_id);
4007 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4008 Renderbuffer* renderbuffer = NULL;
4009 GLuint service_id = 0;
4010 if (client_id != 0) {
4011 renderbuffer = GetRenderbuffer(client_id);
4012 if (!renderbuffer) {
4013 if (!group_->bind_generates_resource()) {
4014 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4015 "glBindRenderbuffer",
4016 "id not generated by glGenRenderbuffers");
4020 // It's a new id so make a renderbuffer renderbuffer for it.
4021 glGenRenderbuffersEXT(1, &service_id);
4022 CreateRenderbuffer(client_id, service_id);
4023 renderbuffer = GetRenderbuffer(client_id);
4024 IdAllocatorInterface* id_allocator =
4025 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
4026 id_allocator->MarkAsUsed(client_id);
4028 service_id = renderbuffer->service_id();
4030 renderbuffer->MarkAsValid();
4032 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4033 state_.bound_renderbuffer = renderbuffer;
4034 glBindRenderbufferEXT(target, service_id);
4037 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4038 TextureRef* texture_ref = NULL;
4039 GLuint service_id = 0;
4040 if (client_id != 0) {
4041 texture_ref = GetTexture(client_id);
4043 if (!group_->bind_generates_resource()) {
4044 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4046 "id not generated by glGenTextures");
4050 // It's a new id so make a texture texture for it.
4051 glGenTextures(1, &service_id);
4052 DCHECK_NE(0u, service_id);
4053 CreateTexture(client_id, service_id);
4054 texture_ref = GetTexture(client_id);
4055 IdAllocatorInterface* id_allocator =
4056 group_->GetIdAllocator(id_namespaces::kTextures);
4057 id_allocator->MarkAsUsed(client_id);
4060 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4063 // Check the texture exists
4065 Texture* texture = texture_ref->texture();
4066 // Check that we are not trying to bind it to a different target.
4067 if (texture->target() != 0 && texture->target() != target) {
4068 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4070 "texture bound to more than 1 target.");
4073 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4074 if (texture->target() == 0) {
4075 texture_manager()->SetTarget(texture_ref, target);
4077 glBindTexture(target, texture->service_id());
4079 glBindTexture(target, 0);
4082 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4083 unit.bind_target = target;
4086 unit.bound_texture_2d = texture_ref;
4088 case GL_TEXTURE_CUBE_MAP:
4089 unit.bound_texture_cube_map = texture_ref;
4091 case GL_TEXTURE_EXTERNAL_OES:
4092 unit.bound_texture_external_oes = texture_ref;
4094 case GL_TEXTURE_RECTANGLE_ARB:
4095 unit.bound_texture_rectangle_arb = texture_ref;
4098 NOTREACHED(); // Validation should prevent us getting here.
4103 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4104 if (state_.vertex_attrib_manager->Enable(index, false)) {
4106 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4107 glDisableVertexAttribArray(index);
4112 "glDisableVertexAttribArray", "index out of range");
4116 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4117 GLsizei numAttachments,
4118 const GLenum* attachments) {
4119 if (!features().ext_discard_framebuffer) {
4120 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4121 "glDiscardFramebufferEXT",
4122 "function not available");
4126 Framebuffer* framebuffer =
4127 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4129 // Validates the attachments. If one of them fails
4130 // the whole command fails.
4131 for (GLsizei i = 0; i < numAttachments; ++i) {
4133 !validators_->attachment.IsValid(attachments[i])) ||
4135 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4136 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4137 "glDiscardFramebufferEXT", attachments[i], "attachments");
4142 // Marks each one of them as not cleared
4143 for (GLsizei i = 0; i < numAttachments; ++i) {
4145 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4150 switch (attachments[i]) {
4152 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4155 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4156 case GL_STENCIL_EXT:
4157 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4166 // If the default framebuffer is bound but we are still rendering to an
4167 // FBO, translate attachment names that refer to default framebuffer
4168 // channels to corresponding framebuffer attachments.
4169 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4170 for (GLsizei i = 0; i < numAttachments; ++i) {
4171 GLenum attachment = attachments[i];
4172 if (!framebuffer && GetBackbufferServiceId()) {
4173 switch (attachment) {
4175 attachment = GL_COLOR_ATTACHMENT0;
4178 attachment = GL_DEPTH_ATTACHMENT;
4180 case GL_STENCIL_EXT:
4181 attachment = GL_STENCIL_ATTACHMENT;
4188 translated_attachments[i] = attachment;
4191 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4194 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4195 if (state_.vertex_attrib_manager->Enable(index, true)) {
4196 glEnableVertexAttribArray(index);
4199 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4203 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4204 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4207 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4209 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4213 if (target == GL_TEXTURE_CUBE_MAP) {
4214 for (int i = 0; i < 6; ++i) {
4215 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4216 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4218 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4223 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4225 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4230 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4231 // Workaround for Mac driver bug. In the large scheme of things setting
4232 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4233 // hit so there's probably no need to make this conditional. The bug appears
4234 // to be that if the filtering mode is set to something that doesn't require
4235 // mipmaps for rendering, or is never set to something other than the default,
4236 // then glGenerateMipmap misbehaves.
4237 if (workarounds().set_texture_filter_before_generating_mipmap) {
4238 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4240 glGenerateMipmapEXT(target);
4241 if (workarounds().set_texture_filter_before_generating_mipmap) {
4242 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4243 texture_ref->texture()->min_filter());
4245 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4246 if (error == GL_NO_ERROR) {
4247 texture_manager()->MarkMipmapsGenerated(texture_ref);
4251 bool GLES2DecoderImpl::GetHelper(
4252 GLenum pname, GLint* params, GLsizei* num_written) {
4253 DCHECK(num_written);
4254 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4256 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4258 // Return the GL implementation's preferred format and (see below type)
4259 // if we have the GL extension that exposes this. This allows the GPU
4260 // client to use the implementation's preferred format for glReadPixels
4261 // for optimisation.
4263 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4264 // case when requested on integer/floating point buffers but which is
4265 // acceptable on GLES2 and with the GL_OES_read_format extension.
4267 // Therefore if an error occurs we swallow the error and use the
4268 // internal implementation.
4270 if (context_->HasExtension("GL_OES_read_format")) {
4271 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4273 glGetIntegerv(pname, params);
4274 if (glGetError() == GL_NO_ERROR)
4277 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4278 GetBoundReadFrameBufferInternalFormat());
4281 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4284 if (context_->HasExtension("GL_OES_read_format")) {
4285 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4287 glGetIntegerv(pname, params);
4288 if (glGetError() == GL_NO_ERROR)
4291 *params = GLES2Util::GetPreferredGLReadPixelsType(
4292 GetBoundReadFrameBufferInternalFormat(),
4293 GetBoundReadFrameBufferTextureType());
4296 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4299 *params = group_->max_fragment_uniform_vectors();
4302 case GL_MAX_VARYING_VECTORS:
4305 *params = group_->max_varying_vectors();
4308 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4311 *params = group_->max_vertex_uniform_vectors();
4317 case GL_MAX_VIEWPORT_DIMS:
4318 if (offscreen_target_frame_buffer_.get()) {
4321 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4322 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4327 case GL_MAX_SAMPLES:
4330 params[0] = renderbuffer_manager()->max_samples();
4333 case GL_MAX_RENDERBUFFER_SIZE:
4336 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4339 case GL_MAX_TEXTURE_SIZE:
4342 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4345 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4348 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4351 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4354 params[0] = group_->max_color_attachments();
4357 case GL_MAX_DRAW_BUFFERS_ARB:
4360 params[0] = group_->max_draw_buffers();
4367 glGetIntegerv(GL_ALPHA_BITS, &v);
4368 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4375 glGetIntegerv(GL_DEPTH_BITS, &v);
4376 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4379 case GL_STENCIL_BITS:
4383 glGetIntegerv(GL_STENCIL_BITS, &v);
4384 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4387 case GL_COMPRESSED_TEXTURE_FORMATS:
4388 *num_written = validators_->compressed_texture_format.GetValues().size();
4390 for (GLint ii = 0; ii < *num_written; ++ii) {
4391 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4395 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4398 *params = validators_->compressed_texture_format.GetValues().size();
4401 case GL_NUM_SHADER_BINARY_FORMATS:
4404 *params = validators_->shader_binary_format.GetValues().size();
4407 case GL_SHADER_BINARY_FORMATS:
4408 *num_written = validators_->shader_binary_format.GetValues().size();
4410 for (GLint ii = 0; ii < *num_written; ++ii) {
4411 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4415 case GL_SHADER_COMPILER:
4421 case GL_ARRAY_BUFFER_BINDING:
4424 if (state_.bound_array_buffer.get()) {
4425 GLuint client_id = 0;
4426 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4428 *params = client_id;
4434 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4437 if (state_.vertex_attrib_manager->element_array_buffer()) {
4438 GLuint client_id = 0;
4439 buffer_manager()->GetClientId(
4440 state_.vertex_attrib_manager->element_array_buffer()->
4441 service_id(), &client_id);
4442 *params = client_id;
4448 case GL_FRAMEBUFFER_BINDING:
4449 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4452 Framebuffer* framebuffer =
4453 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4455 GLuint client_id = 0;
4456 framebuffer_manager()->GetClientId(
4457 framebuffer->service_id(), &client_id);
4458 *params = client_id;
4464 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4467 Framebuffer* framebuffer =
4468 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4470 GLuint client_id = 0;
4471 framebuffer_manager()->GetClientId(
4472 framebuffer->service_id(), &client_id);
4473 *params = client_id;
4479 case GL_RENDERBUFFER_BINDING:
4482 Renderbuffer* renderbuffer =
4483 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4485 *params = renderbuffer->client_id();
4491 case GL_CURRENT_PROGRAM:
4494 if (state_.current_program.get()) {
4495 GLuint client_id = 0;
4496 program_manager()->GetClientId(
4497 state_.current_program->service_id(), &client_id);
4498 *params = client_id;
4504 case GL_VERTEX_ARRAY_BINDING_OES:
4507 if (state_.vertex_attrib_manager.get() !=
4508 state_.default_vertex_attrib_manager.get()) {
4509 GLuint client_id = 0;
4510 vertex_array_manager_->GetClientId(
4511 state_.vertex_attrib_manager->service_id(), &client_id);
4512 *params = client_id;
4518 case GL_TEXTURE_BINDING_2D:
4521 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4522 if (unit.bound_texture_2d.get()) {
4523 *params = unit.bound_texture_2d->client_id();
4529 case GL_TEXTURE_BINDING_CUBE_MAP:
4532 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4533 if (unit.bound_texture_cube_map.get()) {
4534 *params = unit.bound_texture_cube_map->client_id();
4540 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4543 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4544 if (unit.bound_texture_external_oes.get()) {
4545 *params = unit.bound_texture_external_oes->client_id();
4551 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4554 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4555 if (unit.bound_texture_rectangle_arb.get()) {
4556 *params = unit.bound_texture_rectangle_arb->client_id();
4562 case GL_UNPACK_FLIP_Y_CHROMIUM:
4565 params[0] = unpack_flip_y_;
4568 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4571 params[0] = unpack_premultiply_alpha_;
4574 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4577 params[0] = unpack_unpremultiply_alpha_;
4580 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4583 params[0] = group_->bind_generates_resource() ? 1 : 0;
4587 if (pname >= GL_DRAW_BUFFER0_ARB &&
4588 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4591 Framebuffer* framebuffer =
4592 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4594 params[0] = framebuffer->GetDrawBuffer(pname);
4595 } else { // backbuffer
4596 if (pname == GL_DRAW_BUFFER0_ARB)
4597 params[0] = group_->draw_buffer();
4599 params[0] = GL_NONE;
4604 *num_written = util_.GLGetNumValuesReturned(pname);
4609 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4610 GLenum pname, GLsizei* num_values) {
4611 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4614 return GetHelper(pname, NULL, num_values);
4617 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4618 if (GL_MAX_SAMPLES == pname &&
4619 features().use_img_for_multisampled_render_to_texture) {
4620 return GL_MAX_SAMPLES_IMG;
4625 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4627 GLsizei num_written = 0;
4628 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4629 scoped_ptr<GLint[]> values(new GLint[num_written]);
4630 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4631 GetHelper(pname, values.get(), &num_written);
4633 for (GLsizei ii = 0; ii < num_written; ++ii) {
4634 params[ii] = static_cast<GLboolean>(values[ii]);
4637 pname = AdjustGetPname(pname);
4638 glGetBooleanv(pname, params);
4642 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4644 GLsizei num_written = 0;
4645 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4646 if (GetHelper(pname, NULL, &num_written)) {
4647 scoped_ptr<GLint[]> values(new GLint[num_written]);
4648 GetHelper(pname, values.get(), &num_written);
4649 for (GLsizei ii = 0; ii < num_written; ++ii) {
4650 params[ii] = static_cast<GLfloat>(values[ii]);
4653 pname = AdjustGetPname(pname);
4654 glGetFloatv(pname, params);
4659 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4661 GLsizei num_written;
4662 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4663 !GetHelper(pname, params, &num_written)) {
4664 pname = AdjustGetPname(pname);
4665 glGetIntegerv(pname, params);
4669 void GLES2DecoderImpl::DoGetProgramiv(
4670 GLuint program_id, GLenum pname, GLint* params) {
4671 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4675 program->GetProgramiv(pname, params);
4678 void GLES2DecoderImpl::DoGetBufferParameteriv(
4679 GLenum target, GLenum pname, GLint* params) {
4680 // Just delegate it. Some validation is actually done before this.
4681 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4682 &state_, target, pname, params);
4685 void GLES2DecoderImpl::DoBindAttribLocation(
4686 GLuint program_id, GLuint index, const char* name) {
4687 if (!StringIsValidForGLES(name)) {
4689 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4692 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4694 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4697 if (index >= group_->max_vertex_attribs()) {
4699 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4702 Program* program = GetProgramInfoNotShader(
4703 program_id, "glBindAttribLocation");
4707 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4708 glBindAttribLocation(program->service_id(), index, name);
4711 error::Error GLES2DecoderImpl::HandleBindAttribLocation(
4712 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
4713 GLuint program = static_cast<GLuint>(c.program);
4714 GLuint index = static_cast<GLuint>(c.index);
4715 uint32 name_size = c.data_size;
4716 const char* name = GetSharedMemoryAs<const char*>(
4717 c.name_shm_id, c.name_shm_offset, name_size);
4719 return error::kOutOfBounds;
4721 std::string name_str(name, name_size);
4722 DoBindAttribLocation(program, index, name_str.c_str());
4723 return error::kNoError;
4726 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4727 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4728 GLuint program = static_cast<GLuint>(c.program);
4729 GLuint index = static_cast<GLuint>(c.index);
4730 Bucket* bucket = GetBucket(c.name_bucket_id);
4731 if (!bucket || bucket->size() == 0) {
4732 return error::kInvalidArguments;
4734 std::string name_str;
4735 if (!bucket->GetAsString(&name_str)) {
4736 return error::kInvalidArguments;
4738 DoBindAttribLocation(program, index, name_str.c_str());
4739 return error::kNoError;
4742 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4743 GLuint program_id, GLint location, const char* name) {
4744 if (!StringIsValidForGLES(name)) {
4747 "glBindUniformLocationCHROMIUM", "Invalid character");
4750 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4752 GL_INVALID_OPERATION,
4753 "glBindUniformLocationCHROMIUM", "reserved prefix");
4756 if (location < 0 || static_cast<uint32>(location) >=
4757 (group_->max_fragment_uniform_vectors() +
4758 group_->max_vertex_uniform_vectors()) * 4) {
4761 "glBindUniformLocationCHROMIUM", "location out of range");
4764 Program* program = GetProgramInfoNotShader(
4765 program_id, "glBindUniformLocationCHROMIUM");
4769 if (!program->SetUniformLocationBinding(name, location)) {
4772 "glBindUniformLocationCHROMIUM", "location out of range");
4776 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4777 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
4778 GLuint program = static_cast<GLuint>(c.program);
4779 GLint location = static_cast<GLint>(c.location);
4780 uint32 name_size = c.data_size;
4781 const char* name = GetSharedMemoryAs<const char*>(
4782 c.name_shm_id, c.name_shm_offset, name_size);
4784 return error::kOutOfBounds;
4786 std::string name_str(name, name_size);
4787 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4788 return error::kNoError;
4791 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4792 uint32 immediate_data_size,
4793 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4794 GLuint program = static_cast<GLuint>(c.program);
4795 GLint location = static_cast<GLint>(c.location);
4796 Bucket* bucket = GetBucket(c.name_bucket_id);
4797 if (!bucket || bucket->size() == 0) {
4798 return error::kInvalidArguments;
4800 std::string name_str;
4801 if (!bucket->GetAsString(&name_str)) {
4802 return error::kInvalidArguments;
4804 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4805 return error::kNoError;
4808 error::Error GLES2DecoderImpl::HandleDeleteShader(
4809 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4810 GLuint client_id = c.shader;
4812 Shader* shader = GetShader(client_id);
4814 if (!shader->IsDeleted()) {
4815 glDeleteShader(shader->service_id());
4816 shader_manager()->MarkAsDeleted(shader);
4819 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4822 return error::kNoError;
4825 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4826 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4827 GLuint client_id = c.program;
4829 Program* program = GetProgram(client_id);
4831 if (!program->IsDeleted()) {
4832 program_manager()->MarkAsDeleted(shader_manager(), program);
4836 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4839 return error::kNoError;
4842 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4843 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4844 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4845 for (GLsizei ii = 0; ii < n; ++ii) {
4846 id_allocator->FreeID(ids[ii]);
4850 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4851 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4852 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4853 GLsizei n = static_cast<GLsizei>(c.n);
4855 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4856 return error::kOutOfBounds;
4858 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4859 c.ids_shm_id, c.ids_shm_offset, data_size);
4861 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4862 return error::kNoError;
4865 return error::kOutOfBounds;
4867 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4868 return error::kNoError;
4871 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4872 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4873 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4874 if (id_offset == 0) {
4875 for (GLsizei ii = 0; ii < n; ++ii) {
4876 ids[ii] = id_allocator->AllocateID();
4879 for (GLsizei ii = 0; ii < n; ++ii) {
4880 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4881 id_offset = ids[ii] + 1;
4886 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4887 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4888 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4889 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4890 GLsizei n = static_cast<GLsizei>(c.n);
4892 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4893 return error::kOutOfBounds;
4895 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4896 c.ids_shm_id, c.ids_shm_offset, data_size);
4898 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4899 return error::kNoError;
4902 return error::kOutOfBounds;
4904 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4905 return error::kNoError;
4908 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4909 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4910 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4911 for (GLsizei ii = 0; ii < n; ++ii) {
4912 if (!id_allocator->MarkAsUsed(ids[ii])) {
4913 for (GLsizei jj = 0; jj < ii; ++jj) {
4914 id_allocator->FreeID(ids[jj]);
4917 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4918 "attempt to register id that already exists");
4924 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4925 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4926 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4927 GLsizei n = static_cast<GLsizei>(c.n);
4929 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4930 return error::kOutOfBounds;
4932 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4933 c.ids_shm_id, c.ids_shm_offset, data_size);
4935 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4936 return error::kNoError;
4939 return error::kOutOfBounds;
4941 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4942 return error::kNoError;
4945 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4946 DCHECK(!ShouldDeferDraws());
4947 if (CheckBoundFramebuffersValid("glClear")) {
4951 return error::kNoError;
4954 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4955 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4956 GLuint client_renderbuffer_id) {
4957 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4960 GL_INVALID_OPERATION,
4961 "glFramebufferRenderbuffer", "no framebuffer bound");
4964 GLuint service_id = 0;
4965 Renderbuffer* renderbuffer = NULL;
4966 if (client_renderbuffer_id) {
4967 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4968 if (!renderbuffer) {
4970 GL_INVALID_OPERATION,
4971 "glFramebufferRenderbuffer", "unknown renderbuffer");
4974 service_id = renderbuffer->service_id();
4976 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4977 glFramebufferRenderbufferEXT(
4978 target, attachment, renderbuffertarget, service_id);
4979 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4980 if (error == GL_NO_ERROR) {
4981 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4983 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4984 framebuffer_state_.clear_state_dirty = true;
4989 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4990 if (SetCapabilityState(cap, false)) {
4995 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4996 if (SetCapabilityState(cap, true)) {
5001 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5002 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5003 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5004 glDepthRange(znear, zfar);
5007 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5008 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5009 state_.sample_coverage_invert = (invert != 0);
5010 glSampleCoverage(state_.sample_coverage_value, invert);
5013 // Assumes framebuffer is complete.
5014 void GLES2DecoderImpl::ClearUnclearedAttachments(
5015 GLenum target, Framebuffer* framebuffer) {
5016 if (target == GL_READ_FRAMEBUFFER_EXT) {
5017 // bind this to the DRAW point, clear then bind back to READ
5018 // TODO(gman): I don't think there is any guarantee that an FBO that
5019 // is complete on the READ attachment will be complete as a DRAW
5021 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5022 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5024 GLbitfield clear_bits = 0;
5025 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
5028 (GLES2Util::GetChannelsForFormat(
5029 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5031 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5032 clear_bits |= GL_COLOR_BUFFER_BIT;
5035 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5036 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5039 clear_bits |= GL_STENCIL_BUFFER_BIT;
5042 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5043 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5045 state_.SetDeviceDepthMask(GL_TRUE);
5046 clear_bits |= GL_DEPTH_BUFFER_BIT;
5049 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5050 glClear(clear_bits);
5052 framebuffer_manager()->MarkAttachmentsAsCleared(
5053 framebuffer, renderbuffer_manager(), texture_manager());
5055 RestoreClearState();
5057 if (target == GL_READ_FRAMEBUFFER_EXT) {
5058 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5059 Framebuffer* draw_framebuffer =
5060 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5061 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5062 GetBackbufferServiceId();
5063 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5067 void GLES2DecoderImpl::RestoreClearState() {
5068 framebuffer_state_.clear_state_dirty = true;
5070 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5071 state_.color_clear_alpha);
5072 glClearStencil(state_.stencil_clear);
5073 glClearDepth(state_.depth_clear);
5074 if (state_.enable_flags.scissor_test) {
5075 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5079 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5080 Framebuffer* framebuffer =
5081 GetFramebufferInfoForTarget(target);
5083 return GL_FRAMEBUFFER_COMPLETE;
5085 GLenum completeness = framebuffer->IsPossiblyComplete();
5086 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5087 return completeness;
5089 return framebuffer->GetStatus(texture_manager(), target);
5092 void GLES2DecoderImpl::DoFramebufferTexture2D(
5093 GLenum target, GLenum attachment, GLenum textarget,
5094 GLuint client_texture_id, GLint level) {
5095 DoFramebufferTexture2DCommon(
5096 "glFramebufferTexture2D", target, attachment,
5097 textarget, client_texture_id, level, 0);
5100 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5101 GLenum target, GLenum attachment, GLenum textarget,
5102 GLuint client_texture_id, GLint level, GLsizei samples) {
5103 if (!features().multisampled_render_to_texture) {
5105 GL_INVALID_OPERATION,
5106 "glFramebufferTexture2DMultisample", "function not available");
5109 DoFramebufferTexture2DCommon(
5110 "glFramebufferTexture2DMultisample", target, attachment,
5111 textarget, client_texture_id, level, samples);
5114 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5115 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5116 GLuint client_texture_id, GLint level, GLsizei samples) {
5117 if (samples > renderbuffer_manager()->max_samples()) {
5120 "glFramebufferTexture2DMultisample", "samples too large");
5123 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5126 GL_INVALID_OPERATION,
5127 name, "no framebuffer bound.");
5130 GLuint service_id = 0;
5131 TextureRef* texture_ref = NULL;
5132 if (client_texture_id) {
5133 texture_ref = GetTexture(client_texture_id);
5136 GL_INVALID_OPERATION,
5137 name, "unknown texture_ref");
5140 service_id = texture_ref->service_id();
5143 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5146 name, "level out of range");
5151 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5153 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5155 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5157 if (features().use_img_for_multisampled_render_to_texture) {
5158 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5159 service_id, level, samples);
5161 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5162 service_id, level, samples);
5165 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5166 if (error == GL_NO_ERROR) {
5167 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5170 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5171 framebuffer_state_.clear_state_dirty = true;
5175 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5180 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5181 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5182 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5185 GL_INVALID_OPERATION,
5186 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5189 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5190 const Framebuffer::Attachment* attachment_object =
5191 framebuffer->GetAttachment(attachment);
5192 *params = attachment_object ? attachment_object->object_name() : 0;
5194 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5195 features().use_img_for_multisampled_render_to_texture) {
5196 pname = GL_TEXTURE_SAMPLES_IMG;
5198 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5202 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5203 GLenum target, GLenum pname, GLint* params) {
5204 Renderbuffer* renderbuffer =
5205 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5206 if (!renderbuffer) {
5208 GL_INVALID_OPERATION,
5209 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5213 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5214 *params = renderbuffer->internal_format();
5216 case GL_RENDERBUFFER_WIDTH:
5217 *params = renderbuffer->width();
5219 case GL_RENDERBUFFER_HEIGHT:
5220 *params = renderbuffer->height();
5222 case GL_RENDERBUFFER_SAMPLES_EXT:
5223 if (features().use_img_for_multisampled_render_to_texture) {
5224 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5227 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5231 glGetRenderbufferParameterivEXT(target, pname, params);
5236 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5237 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5238 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5239 GLbitfield mask, GLenum filter) {
5240 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5241 if (!features().chromium_framebuffer_multisample) {
5243 GL_INVALID_OPERATION,
5244 "glBlitFramebufferCHROMIUM", "function not available");
5248 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5252 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5253 BlitFramebufferHelper(
5254 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5255 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5256 state_.enable_flags.scissor_test);
5259 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5260 const FeatureInfo* feature_info,
5263 GLenum internal_format,
5266 // TODO(sievers): This could be resolved at the GL binding level, but the
5267 // binding process is currently a bit too 'brute force'.
5268 if (feature_info->feature_flags().is_angle) {
5269 glRenderbufferStorageMultisampleANGLE(
5270 target, samples, internal_format, width, height);
5271 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5272 glRenderbufferStorageMultisample(
5273 target, samples, internal_format, width, height);
5275 glRenderbufferStorageMultisampleEXT(
5276 target, samples, internal_format, width, height);
5280 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5290 // TODO(sievers): This could be resolved at the GL binding level, but the
5291 // binding process is currently a bit too 'brute force'.
5292 if (feature_info_->feature_flags().is_angle) {
5293 glBlitFramebufferANGLE(
5294 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5295 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5297 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5299 glBlitFramebufferEXT(
5300 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5304 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5306 GLenum internalformat,
5309 if (samples > renderbuffer_manager()->max_samples()) {
5312 "glRenderbufferStorageMultisample", "samples too large");
5316 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5317 height > renderbuffer_manager()->max_renderbuffer_size()) {
5320 "glRenderbufferStorageMultisample", "dimensions too large");
5324 uint32 estimated_size = 0;
5325 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5326 width, height, samples, internalformat, &estimated_size)) {
5329 "glRenderbufferStorageMultisample", "dimensions too large");
5333 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5336 "glRenderbufferStorageMultisample", "out of memory");
5343 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5344 GLenum target, GLsizei samples, GLenum internalformat,
5345 GLsizei width, GLsizei height) {
5346 if (!features().chromium_framebuffer_multisample) {
5347 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5348 "glRenderbufferStorageMultisampleCHROMIUM",
5349 "function not available");
5353 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5354 if (!renderbuffer) {
5355 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5356 "glRenderbufferStorageMultisampleCHROMIUM",
5357 "no renderbuffer bound");
5361 if (!ValidateRenderbufferStorageMultisample(
5362 samples, internalformat, width, height)) {
5366 GLenum impl_format =
5367 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5369 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5370 "glRenderbufferStorageMultisampleCHROMIUM");
5371 RenderbufferStorageMultisampleHelper(
5372 feature_info_, target, samples, impl_format, width, height);
5374 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5375 if (error == GL_NO_ERROR) {
5377 if (workarounds().validate_multisample_buffer_allocation) {
5378 if (!VerifyMultisampleRenderbufferIntegrity(
5379 renderbuffer->service_id(), impl_format)) {
5382 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5387 // TODO(gman): If renderbuffers tracked which framebuffers they were
5388 // attached to we could just mark those framebuffers as not complete.
5389 framebuffer_manager()->IncFramebufferStateChangeCount();
5390 renderbuffer_manager()->SetInfo(
5391 renderbuffer, samples, internalformat, width, height);
5395 // This is the handler for multisampled_render_to_texture extensions.
5396 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5397 GLenum target, GLsizei samples, GLenum internalformat,
5398 GLsizei width, GLsizei height) {
5399 if (!features().multisampled_render_to_texture) {
5401 GL_INVALID_OPERATION,
5402 "glRenderbufferStorageMultisampleEXT", "function not available");
5406 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5407 if (!renderbuffer) {
5408 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5409 "glRenderbufferStorageMultisampleEXT",
5410 "no renderbuffer bound");
5414 if (!ValidateRenderbufferStorageMultisample(
5415 samples, internalformat, width, height)) {
5419 GLenum impl_format =
5420 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5422 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5423 if (features().use_img_for_multisampled_render_to_texture) {
5424 glRenderbufferStorageMultisampleIMG(
5425 target, samples, impl_format, width, height);
5427 glRenderbufferStorageMultisampleEXT(
5428 target, samples, impl_format, width, height);
5430 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5431 if (error == GL_NO_ERROR) {
5432 // TODO(gman): If renderbuffers tracked which framebuffers they were
5433 // attached to we could just mark those framebuffers as not complete.
5434 framebuffer_manager()->IncFramebufferStateChangeCount();
5435 renderbuffer_manager()->SetInfo(
5436 renderbuffer, samples, internalformat, width, height);
5440 // This function validates the allocation of a multisampled renderbuffer
5441 // by clearing it to a key color, blitting the contents to a texture, and
5442 // reading back the color to ensure it matches the key.
5443 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5444 GLuint renderbuffer, GLenum format) {
5446 // Only validate color buffers.
5447 // These formats have been selected because they are very common or are known
5448 // to be used by the WebGL backbuffer. If problems are observed with other
5449 // color formats they can be added here.
5460 GLint draw_framebuffer, read_framebuffer;
5462 // Cache framebuffer and texture bindings.
5463 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5464 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5466 if (!validation_texture_) {
5467 GLint bound_texture;
5468 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5470 // Create additional resources needed for the verification.
5471 glGenTextures(1, &validation_texture_);
5472 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5473 glGenFramebuffersEXT(1, &validation_fbo_);
5475 // Texture only needs to be 1x1.
5476 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5477 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5478 GL_UNSIGNED_BYTE, NULL);
5480 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5481 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5482 GL_TEXTURE_2D, validation_texture_, 0);
5484 glBindTexture(GL_TEXTURE_2D, bound_texture);
5487 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5488 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5489 GL_RENDERBUFFER, renderbuffer);
5491 // Cache current state and reset it to the values we require.
5492 GLboolean scissor_enabled = false;
5493 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5494 if (scissor_enabled)
5495 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5497 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5498 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5499 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5501 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5502 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5503 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5505 // Clear the buffer to the desired key color.
5506 glClear(GL_COLOR_BUFFER_BIT);
5508 // Blit from the multisample buffer to a standard texture.
5509 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5510 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5512 BlitFramebufferHelper(
5513 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5515 // Read a pixel from the buffer.
5516 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5518 unsigned char pixel[3] = {0, 0, 0};
5519 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5521 // Detach the renderbuffer.
5522 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5523 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5524 GL_RENDERBUFFER, 0);
5526 // Restore cached state.
5527 if (scissor_enabled)
5528 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5530 state_.SetDeviceColorMask(
5531 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5532 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5533 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5534 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5536 // Return true if the pixel matched the desired key color.
5537 return (pixel[0] == 0xFF &&
5542 void GLES2DecoderImpl::DoRenderbufferStorage(
5543 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5544 Renderbuffer* renderbuffer =
5545 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5546 if (!renderbuffer) {
5548 GL_INVALID_OPERATION,
5549 "glRenderbufferStorage", "no renderbuffer bound");
5553 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5554 height > renderbuffer_manager()->max_renderbuffer_size()) {
5556 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5560 uint32 estimated_size = 0;
5561 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5562 width, height, 1, internalformat, &estimated_size)) {
5564 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5568 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5570 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5574 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5575 glRenderbufferStorageEXT(
5577 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5581 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5582 if (error == GL_NO_ERROR) {
5583 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5584 // we could just mark those framebuffers as not complete.
5585 framebuffer_manager()->IncFramebufferStateChangeCount();
5586 renderbuffer_manager()->SetInfo(
5587 renderbuffer, 1, internalformat, width, height);
5591 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5592 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5593 Program* program = GetProgramInfoNotShader(
5594 program_id, "glLinkProgram");
5599 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5600 ShaderTranslator* vertex_translator = NULL;
5601 ShaderTranslator* fragment_translator = NULL;
5602 if (use_shader_translator_) {
5603 vertex_translator = vertex_translator_.get();
5604 fragment_translator = fragment_translator_.get();
5606 if (program->Link(shader_manager(),
5608 fragment_translator,
5609 workarounds().count_all_in_varyings_packing ?
5610 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5611 shader_cache_callback_)) {
5612 if (program == state_.current_program.get()) {
5613 if (workarounds().use_current_program_after_successful_link)
5614 glUseProgram(program->service_id());
5615 if (workarounds().clear_uniforms_before_first_program_use)
5616 program_manager()->ClearUniforms(program);
5621 void GLES2DecoderImpl::DoTexParameterf(
5622 GLenum target, GLenum pname, GLfloat param) {
5623 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5626 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5630 texture_manager()->SetParameterf(
5631 "glTexParameterf", GetErrorState(), texture, pname, param);
5634 void GLES2DecoderImpl::DoTexParameteri(
5635 GLenum target, GLenum pname, GLint param) {
5636 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5639 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5643 texture_manager()->SetParameteri(
5644 "glTexParameteri", GetErrorState(), texture, pname, param);
5647 void GLES2DecoderImpl::DoTexParameterfv(
5648 GLenum target, GLenum pname, const GLfloat* params) {
5649 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5652 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5656 texture_manager()->SetParameterf(
5657 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5660 void GLES2DecoderImpl::DoTexParameteriv(
5661 GLenum target, GLenum pname, const GLint* params) {
5662 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5666 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5670 texture_manager()->SetParameteri(
5671 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5674 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5675 if (!state_.current_program.get()) {
5676 // The program does not exist.
5678 GL_INVALID_OPERATION, function_name, "no program in use");
5681 if (!state_.current_program->InUse()) {
5683 GL_INVALID_OPERATION, function_name, "program not linked");
5689 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5690 GLint location, const char* function_name) {
5691 if (!CheckCurrentProgram(function_name)) {
5694 return location != -1;
5697 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5698 GLint fake_location,
5699 const char* function_name,
5700 Program::UniformApiType api_type,
5701 GLint* real_location,
5706 DCHECK(real_location);
5708 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5711 GLint array_index = -1;
5712 const Program::UniformInfo* info =
5713 state_.current_program->GetUniformInfoByFakeLocation(
5714 fake_location, real_location, &array_index);
5717 GL_INVALID_OPERATION, function_name, "unknown location");
5721 if ((api_type & info->accepts_api_type) == 0) {
5723 GL_INVALID_OPERATION, function_name,
5724 "wrong uniform function for type");
5727 if (*count > 1 && !info->is_array) {
5729 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5732 *count = std::min(info->size - array_index, *count);
5740 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5743 GLint real_location = -1;
5744 if (!PrepForSetUniformByLocation(fake_location,
5746 Program::kUniform1i,
5752 if (!state_.current_program->SetSamplers(
5753 state_.texture_units.size(), fake_location, 1, &v0)) {
5755 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5758 glUniform1i(real_location, v0);
5761 void GLES2DecoderImpl::DoUniform1iv(
5762 GLint fake_location, GLsizei count, const GLint *value) {
5764 GLint real_location = -1;
5765 if (!PrepForSetUniformByLocation(fake_location,
5767 Program::kUniform1i,
5773 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5774 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5775 if (!state_.current_program->SetSamplers(
5776 state_.texture_units.size(), fake_location, count, value)) {
5778 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5782 glUniform1iv(real_location, count, value);
5785 void GLES2DecoderImpl::DoUniform1fv(
5786 GLint fake_location, GLsizei count, const GLfloat* value) {
5788 GLint real_location = -1;
5789 if (!PrepForSetUniformByLocation(fake_location,
5791 Program::kUniform1f,
5797 if (type == GL_BOOL) {
5798 scoped_ptr<GLint[]> temp(new GLint[count]);
5799 for (GLsizei ii = 0; ii < count; ++ii) {
5800 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5802 DoUniform1iv(real_location, count, temp.get());
5804 glUniform1fv(real_location, count, value);
5808 void GLES2DecoderImpl::DoUniform2fv(
5809 GLint fake_location, GLsizei count, const GLfloat* value) {
5811 GLint real_location = -1;
5812 if (!PrepForSetUniformByLocation(fake_location,
5814 Program::kUniform2f,
5820 if (type == GL_BOOL_VEC2) {
5821 GLsizei num_values = count * 2;
5822 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5823 for (GLsizei ii = 0; ii < num_values; ++ii) {
5824 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5826 glUniform2iv(real_location, count, temp.get());
5828 glUniform2fv(real_location, count, value);
5832 void GLES2DecoderImpl::DoUniform3fv(
5833 GLint fake_location, GLsizei count, const GLfloat* value) {
5835 GLint real_location = -1;
5836 if (!PrepForSetUniformByLocation(fake_location,
5838 Program::kUniform3f,
5844 if (type == GL_BOOL_VEC3) {
5845 GLsizei num_values = count * 3;
5846 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5847 for (GLsizei ii = 0; ii < num_values; ++ii) {
5848 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5850 glUniform3iv(real_location, count, temp.get());
5852 glUniform3fv(real_location, count, value);
5856 void GLES2DecoderImpl::DoUniform4fv(
5857 GLint fake_location, GLsizei count, const GLfloat* value) {
5859 GLint real_location = -1;
5860 if (!PrepForSetUniformByLocation(fake_location,
5862 Program::kUniform4f,
5868 if (type == GL_BOOL_VEC4) {
5869 GLsizei num_values = count * 4;
5870 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5871 for (GLsizei ii = 0; ii < num_values; ++ii) {
5872 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5874 glUniform4iv(real_location, count, temp.get());
5876 glUniform4fv(real_location, count, value);
5880 void GLES2DecoderImpl::DoUniform2iv(
5881 GLint fake_location, GLsizei count, const GLint* value) {
5883 GLint real_location = -1;
5884 if (!PrepForSetUniformByLocation(fake_location,
5886 Program::kUniform2i,
5892 glUniform2iv(real_location, count, value);
5895 void GLES2DecoderImpl::DoUniform3iv(
5896 GLint fake_location, GLsizei count, const GLint* value) {
5898 GLint real_location = -1;
5899 if (!PrepForSetUniformByLocation(fake_location,
5901 Program::kUniform3i,
5907 glUniform3iv(real_location, count, value);
5910 void GLES2DecoderImpl::DoUniform4iv(
5911 GLint fake_location, GLsizei count, const GLint* value) {
5913 GLint real_location = -1;
5914 if (!PrepForSetUniformByLocation(fake_location,
5916 Program::kUniform4i,
5922 glUniform4iv(real_location, count, value);
5925 void GLES2DecoderImpl::DoUniformMatrix2fv(
5926 GLint fake_location, GLsizei count, GLboolean transpose,
5927 const GLfloat* value) {
5929 GLint real_location = -1;
5930 if (!PrepForSetUniformByLocation(fake_location,
5931 "glUniformMatrix2fv",
5932 Program::kUniformMatrix2f,
5938 glUniformMatrix2fv(real_location, count, transpose, value);
5941 void GLES2DecoderImpl::DoUniformMatrix3fv(
5942 GLint fake_location, GLsizei count, GLboolean transpose,
5943 const GLfloat* value) {
5945 GLint real_location = -1;
5946 if (!PrepForSetUniformByLocation(fake_location,
5947 "glUniformMatrix3fv",
5948 Program::kUniformMatrix3f,
5954 glUniformMatrix3fv(real_location, count, transpose, value);
5957 void GLES2DecoderImpl::DoUniformMatrix4fv(
5958 GLint fake_location, GLsizei count, GLboolean transpose,
5959 const GLfloat* value) {
5961 GLint real_location = -1;
5962 if (!PrepForSetUniformByLocation(fake_location,
5963 "glUniformMatrix4fv",
5964 Program::kUniformMatrix4f,
5970 glUniformMatrix4fv(real_location, count, transpose, value);
5973 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5974 GLuint service_id = 0;
5975 Program* program = NULL;
5977 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5981 if (!program->IsValid()) {
5982 // Program was not linked successfully. (ie, glLinkProgram)
5984 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5987 service_id = program->service_id();
5989 if (state_.current_program.get()) {
5990 program_manager()->UnuseProgram(shader_manager(),
5991 state_.current_program.get());
5993 state_.current_program = program;
5994 LogClientServiceMapping("glUseProgram", program_id, service_id);
5995 glUseProgram(service_id);
5996 if (state_.current_program.get()) {
5997 program_manager()->UseProgram(state_.current_program.get());
5998 if (workarounds().clear_uniforms_before_first_program_use)
5999 program_manager()->ClearUniforms(program);
6003 void GLES2DecoderImpl::RenderWarning(
6004 const char* filename, int line, const std::string& msg) {
6005 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6008 void GLES2DecoderImpl::PerformanceWarning(
6009 const char* filename, int line, const std::string& msg) {
6010 logger_.LogMessage(filename, line,
6011 std::string("PERFORMANCE WARNING: ") + msg);
6014 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6015 Texture* texture, GLenum textarget) {
6016 // Image is already in use if texture is attached to a framebuffer.
6017 if (texture && !texture->IsAttachedToFramebuffer()) {
6018 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6020 ScopedGLErrorSuppressor suppressor(
6021 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6023 glBindTexture(textarget, texture->service_id());
6024 image->WillUseTexImage();
6025 RestoreCurrentTextureBindings(&state_, textarget);
6030 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6031 Texture* texture, GLenum textarget) {
6032 // Image is still in use if texture is attached to a framebuffer.
6033 if (texture && !texture->IsAttachedToFramebuffer()) {
6034 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6036 ScopedGLErrorSuppressor suppressor(
6037 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6039 glBindTexture(textarget, texture->service_id());
6040 image->DidUseTexImage();
6041 RestoreCurrentTextureBindings(&state_, textarget);
6046 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6047 DCHECK(state_.current_program.get());
6048 if (!texture_manager()->HaveUnrenderableTextures() &&
6049 !texture_manager()->HaveImages()) {
6053 bool textures_set = false;
6054 const Program::SamplerIndices& sampler_indices =
6055 state_.current_program->sampler_indices();
6056 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6057 const Program::UniformInfo* uniform_info =
6058 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6059 DCHECK(uniform_info);
6060 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6061 GLuint texture_unit_index = uniform_info->texture_units[jj];
6062 if (texture_unit_index < state_.texture_units.size()) {
6063 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6064 TextureRef* texture_ref =
6065 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6066 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6067 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6068 textures_set = true;
6069 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6072 texture_manager()->black_texture_id(uniform_info->type));
6073 LOCAL_RENDER_WARNING(
6074 std::string("texture bound to texture unit ") +
6075 base::IntToString(texture_unit_index) +
6076 " is not renderable. It maybe non-power-of-2 and have"
6077 " incompatible texture filtering or is not"
6078 " 'texture complete'");
6082 if (textarget != GL_TEXTURE_CUBE_MAP) {
6083 Texture* texture = texture_ref->texture();
6084 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6085 if (image && !texture->IsAttachedToFramebuffer()) {
6086 ScopedGLErrorSuppressor suppressor(
6087 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6088 textures_set = true;
6089 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6090 image->WillUseTexImage();
6095 // else: should this be an error?
6098 return !textures_set;
6101 void GLES2DecoderImpl::RestoreStateForTextures() {
6102 DCHECK(state_.current_program.get());
6103 const Program::SamplerIndices& sampler_indices =
6104 state_.current_program->sampler_indices();
6105 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6106 const Program::UniformInfo* uniform_info =
6107 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6108 DCHECK(uniform_info);
6109 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6110 GLuint texture_unit_index = uniform_info->texture_units[jj];
6111 if (texture_unit_index < state_.texture_units.size()) {
6112 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6113 TextureRef* texture_ref =
6114 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6115 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6116 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6117 // Get the texture_ref info that was previously bound here.
6118 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6119 ? texture_unit.bound_texture_2d.get()
6120 : texture_unit.bound_texture_cube_map.get();
6121 glBindTexture(texture_unit.bind_target,
6122 texture_ref ? texture_ref->service_id() : 0);
6126 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6127 Texture* texture = texture_ref->texture();
6128 gfx::GLImage* image =
6129 texture->GetLevelImage(texture_unit.bind_target, 0);
6130 if (image && !texture->IsAttachedToFramebuffer()) {
6131 ScopedGLErrorSuppressor suppressor(
6132 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6133 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6134 image->DidUseTexImage();
6141 // Set the active texture back to whatever the user had it as.
6142 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6145 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6146 // Only check if there are some uncleared textures.
6147 if (!texture_manager()->HaveUnsafeTextures()) {
6151 // 1: Check all textures we are about to render with.
6152 if (state_.current_program.get()) {
6153 const Program::SamplerIndices& sampler_indices =
6154 state_.current_program->sampler_indices();
6155 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6156 const Program::UniformInfo* uniform_info =
6157 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6158 DCHECK(uniform_info);
6159 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6160 GLuint texture_unit_index = uniform_info->texture_units[jj];
6161 if (texture_unit_index < state_.texture_units.size()) {
6162 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6163 TextureRef* texture_ref =
6164 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6165 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6166 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6177 bool GLES2DecoderImpl::IsDrawValid(
6178 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
6179 // NOTE: We specifically do not check current_program->IsValid() because
6180 // it could never be invalid since glUseProgram would have failed. While
6181 // glLinkProgram could later mark the program as invalid the previous
6182 // valid program will still function if it is still the current program.
6183 if (!state_.current_program.get()) {
6184 // The program does not exist.
6185 // But GL says no ERROR.
6186 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6190 return state_.vertex_attrib_manager
6191 ->ValidateBindings(function_name,
6193 feature_info_.get(),
6194 state_.current_program.get(),
6195 max_vertex_accessed,
6199 bool GLES2DecoderImpl::SimulateAttrib0(
6200 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6204 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6207 const VertexAttrib* attrib =
6208 state_.vertex_attrib_manager->GetVertexAttrib(0);
6209 // If it's enabled or it's not used then we don't need to do anything.
6210 bool attrib_0_used =
6211 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6212 if (attrib->enabled() && attrib_0_used) {
6216 // Make a buffer with a single repeated vec4 value enough to
6217 // simulate the constant value that is supposed to be here.
6218 // This is required to emulate GLES2 on GL.
6219 GLuint num_vertices = max_vertex_accessed + 1;
6220 uint32 size_needed = 0;
6222 if (num_vertices == 0 ||
6223 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6224 size_needed > 0x7FFFFFFFU) {
6225 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6229 LOCAL_PERFORMANCE_WARNING(
6230 "Attribute 0 is disabled. This has signficant performance penalty");
6232 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6233 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6235 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6237 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6238 GLenum error = glGetError();
6239 if (error != GL_NO_ERROR) {
6241 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6246 const Vec4& value = state_.attrib_values[0];
6249 (!attrib_0_buffer_matches_value_ ||
6250 (value.v[0] != attrib_0_value_.v[0] ||
6251 value.v[1] != attrib_0_value_.v[1] ||
6252 value.v[2] != attrib_0_value_.v[2] ||
6253 value.v[3] != attrib_0_value_.v[3])))) {
6254 std::vector<Vec4> temp(num_vertices, value);
6255 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6256 attrib_0_buffer_matches_value_ = true;
6257 attrib_0_value_ = value;
6258 attrib_0_size_ = size_needed;
6261 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6263 if (attrib->divisor())
6264 glVertexAttribDivisorANGLE(0, 0);
6270 void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
6271 const VertexAttrib* attrib =
6272 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6273 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6274 Buffer* buffer = attrib->buffer();
6275 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6276 glVertexAttribPointer(
6277 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6278 attrib->gl_stride(), ptr);
6279 if (attrib->divisor())
6280 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6283 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6286 // Never touch vertex attribute 0's state (in particular, never
6287 // disable it) when running on desktop GL because it will never be
6289 if (attrib_index != 0 ||
6290 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6291 if (attrib->enabled()) {
6292 glEnableVertexAttribArray(attrib_index);
6294 glDisableVertexAttribArray(attrib_index);
6299 bool GLES2DecoderImpl::SimulateFixedAttribs(
6300 const char* function_name,
6301 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6304 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6307 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6311 LOCAL_PERFORMANCE_WARNING(
6312 "GL_FIXED attributes have a signficant performance penalty");
6314 // NOTE: we could be smart and try to check if a buffer is used
6315 // twice in 2 different attribs, find the overlapping parts and therefore
6316 // duplicate the minimum amount of data but this whole code path is not meant
6317 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6318 // tests so we just add to the buffer attrib used.
6320 GLuint elements_needed = 0;
6321 const VertexAttribManager::VertexAttribList& enabled_attribs =
6322 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6323 for (VertexAttribManager::VertexAttribList::const_iterator it =
6324 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6325 const VertexAttrib* attrib = *it;
6326 const Program::VertexAttrib* attrib_info =
6327 state_.current_program->GetAttribInfoByLocation(attrib->index());
6328 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6329 max_vertex_accessed);
6330 GLuint num_vertices = max_accessed + 1;
6331 if (num_vertices == 0) {
6333 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6337 attrib->CanAccess(max_accessed) &&
6338 attrib->type() == GL_FIXED) {
6339 uint32 elements_used = 0;
6340 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6341 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6343 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6349 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6350 uint32 size_needed = 0;
6351 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6352 size_needed > 0x7FFFFFFFU) {
6354 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6358 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6360 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6361 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6362 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6363 GLenum error = glGetError();
6364 if (error != GL_NO_ERROR) {
6366 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6371 // Copy the elements and convert to float
6372 GLintptr offset = 0;
6373 for (VertexAttribManager::VertexAttribList::const_iterator it =
6374 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6375 const VertexAttrib* attrib = *it;
6376 const Program::VertexAttrib* attrib_info =
6377 state_.current_program->GetAttribInfoByLocation(attrib->index());
6378 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6379 max_vertex_accessed);
6380 GLuint num_vertices = max_accessed + 1;
6381 if (num_vertices == 0) {
6383 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6387 attrib->CanAccess(max_accessed) &&
6388 attrib->type() == GL_FIXED) {
6389 int num_elements = attrib->size() * kSizeOfFloat;
6390 int size = num_elements * num_vertices;
6391 scoped_ptr<float[]> data(new float[size]);
6392 const int32* src = reinterpret_cast<const int32 *>(
6393 attrib->buffer()->GetRange(attrib->offset(), size));
6394 const int32* end = src + num_elements;
6395 float* dst = data.get();
6396 while (src != end) {
6397 *dst++ = static_cast<float>(*src++) / 65536.0f;
6399 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6400 glVertexAttribPointer(
6401 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6402 reinterpret_cast<GLvoid*>(offset));
6410 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6411 // There's no need to call glVertexAttribPointer because we shadow all the
6412 // settings and passing GL_FIXED to it will not work.
6415 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6419 error::Error GLES2DecoderImpl::DoDrawArrays(
6420 const char* function_name,
6425 GLsizei primcount) {
6426 error::Error error = WillAccessBoundFramebufferForDraw();
6427 if (error != error::kNoError)
6429 if (!validators_->draw_mode.IsValid(mode)) {
6430 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6431 return error::kNoError;
6434 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6435 return error::kNoError;
6437 if (primcount < 0) {
6438 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6439 return error::kNoError;
6441 if (!CheckBoundFramebuffersValid(function_name)) {
6442 return error::kNoError;
6444 // We have to check this here because the prototype for glDrawArrays
6445 // is GLint not GLsizei.
6447 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6448 return error::kNoError;
6451 if (count == 0 || (instanced && primcount == 0)) {
6452 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6453 return error::kNoError;
6456 GLuint max_vertex_accessed = first + count - 1;
6457 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6458 if (!ClearUnclearedTextures()) {
6459 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6460 return error::kNoError;
6462 bool simulated_attrib_0 = false;
6463 if (!SimulateAttrib0(
6464 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6465 return error::kNoError;
6467 bool simulated_fixed_attribs = false;
6468 if (SimulateFixedAttribs(
6469 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6471 bool textures_set = !PrepareTexturesForRender();
6473 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6475 glDrawArrays(mode, first, count);
6477 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6479 ProcessPendingQueries();
6481 RestoreStateForTextures();
6483 if (simulated_fixed_attribs) {
6484 RestoreStateForSimulatedFixedAttribs();
6487 if (simulated_attrib_0) {
6488 RestoreStateForAttrib(0);
6491 return error::kNoError;
6494 error::Error GLES2DecoderImpl::HandleDrawArrays(
6495 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6496 return DoDrawArrays("glDrawArrays",
6498 static_cast<GLenum>(c.mode),
6499 static_cast<GLint>(c.first),
6500 static_cast<GLsizei>(c.count),
6504 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6505 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6506 if (!features().angle_instanced_arrays) {
6508 GL_INVALID_OPERATION,
6509 "glDrawArraysInstancedANGLE", "function not available");
6510 return error::kNoError;
6512 return DoDrawArrays("glDrawArraysIntancedANGLE",
6514 static_cast<GLenum>(c.mode),
6515 static_cast<GLint>(c.first),
6516 static_cast<GLsizei>(c.count),
6517 static_cast<GLsizei>(c.primcount));
6520 error::Error GLES2DecoderImpl::DoDrawElements(
6521 const char* function_name,
6527 GLsizei primcount) {
6528 error::Error error = WillAccessBoundFramebufferForDraw();
6529 if (error != error::kNoError)
6531 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6533 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6534 return error::kNoError;
6538 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6539 return error::kNoError;
6542 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6543 return error::kNoError;
6545 if (!validators_->draw_mode.IsValid(mode)) {
6546 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6547 return error::kNoError;
6549 if (!validators_->index_type.IsValid(type)) {
6550 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6551 return error::kNoError;
6553 if (primcount < 0) {
6554 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6555 return error::kNoError;
6558 if (!CheckBoundFramebuffersValid(function_name)) {
6559 return error::kNoError;
6562 if (count == 0 || (instanced && primcount == 0)) {
6563 return error::kNoError;
6566 GLuint max_vertex_accessed;
6567 Buffer* element_array_buffer =
6568 state_.vertex_attrib_manager->element_array_buffer();
6570 if (!element_array_buffer->GetMaxValueForRange(
6571 offset, count, type, &max_vertex_accessed)) {
6573 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6574 return error::kNoError;
6577 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6578 if (!ClearUnclearedTextures()) {
6579 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6580 return error::kNoError;
6582 bool simulated_attrib_0 = false;
6583 if (!SimulateAttrib0(
6584 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6585 return error::kNoError;
6587 bool simulated_fixed_attribs = false;
6588 if (SimulateFixedAttribs(
6589 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6591 bool textures_set = !PrepareTexturesForRender();
6593 // TODO(gman): Refactor to hide these details in BufferManager or
6594 // VertexAttribManager.
6595 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6596 bool used_client_side_array = false;
6597 if (element_array_buffer->IsClientSideArray()) {
6598 used_client_side_array = true;
6599 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6600 indices = element_array_buffer->GetRange(offset, 0);
6603 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6605 glDrawElements(mode, count, type, indices);
6607 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6610 if (used_client_side_array) {
6611 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6612 element_array_buffer->service_id());
6615 ProcessPendingQueries();
6617 RestoreStateForTextures();
6619 if (simulated_fixed_attribs) {
6620 RestoreStateForSimulatedFixedAttribs();
6623 if (simulated_attrib_0) {
6624 RestoreStateForAttrib(0);
6627 return error::kNoError;
6630 error::Error GLES2DecoderImpl::HandleDrawElements(
6631 uint32 immediate_data_size, const cmds::DrawElements& c) {
6632 return DoDrawElements("glDrawElements",
6634 static_cast<GLenum>(c.mode),
6635 static_cast<GLsizei>(c.count),
6636 static_cast<GLenum>(c.type),
6637 static_cast<int32>(c.index_offset),
6641 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6642 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6643 if (!features().angle_instanced_arrays) {
6645 GL_INVALID_OPERATION,
6646 "glDrawElementsInstancedANGLE", "function not available");
6647 return error::kNoError;
6649 return DoDrawElements("glDrawElementsInstancedANGLE",
6651 static_cast<GLenum>(c.mode),
6652 static_cast<GLsizei>(c.count),
6653 static_cast<GLenum>(c.type),
6654 static_cast<int32>(c.index_offset),
6655 static_cast<GLsizei>(c.primcount));
6658 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6659 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6660 GLuint max_vertex_accessed = 0;
6661 Buffer* buffer = GetBuffer(buffer_id);
6663 // TODO(gman): Should this be a GL error or a command buffer error?
6665 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6667 if (!buffer->GetMaxValueForRange(
6668 offset, count, type, &max_vertex_accessed)) {
6669 // TODO(gman): Should this be a GL error or a command buffer error?
6671 GL_INVALID_OPERATION,
6672 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6675 return max_vertex_accessed;
6678 // Calls glShaderSource for the various versions of the ShaderSource command.
6679 // Assumes that data / data_size points to a piece of memory that is in range
6680 // of whatever context it came from (shared memory, immediate memory, bucket
6682 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6683 GLuint client_id, const char* data, uint32 data_size) {
6684 std::string str(data, data + data_size);
6685 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6687 return error::kNoError;
6689 // Note: We don't actually call glShaderSource here. We wait until
6690 // the call to glCompileShader.
6691 shader->UpdateSource(str.c_str());
6692 return error::kNoError;
6695 error::Error GLES2DecoderImpl::HandleShaderSource(
6696 uint32 immediate_data_size, const cmds::ShaderSource& c) {
6697 uint32 data_size = c.data_size;
6698 const char* data = GetSharedMemoryAs<const char*>(
6699 c.data_shm_id, c.data_shm_offset, data_size);
6701 return error::kOutOfBounds;
6703 return ShaderSourceHelper(c.shader, data, data_size);
6706 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6707 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6708 Bucket* bucket = GetBucket(c.data_bucket_id);
6709 if (!bucket || bucket->size() == 0) {
6710 return error::kInvalidArguments;
6712 return ShaderSourceHelper(
6713 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6714 bucket->size() - 1);
6717 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6718 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6719 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6723 ShaderTranslator* translator = NULL;
6724 if (use_shader_translator_) {
6725 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6726 vertex_translator_.get() : fragment_translator_.get();
6729 program_manager()->DoCompileShader(
6732 feature_info_->feature_flags().angle_translated_shader_source ?
6733 ProgramManager::kANGLE : ProgramManager::kGL);
6736 void GLES2DecoderImpl::DoGetShaderiv(
6737 GLuint shader_id, GLenum pname, GLint* params) {
6738 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6743 case GL_SHADER_SOURCE_LENGTH:
6744 *params = shader->source() ? shader->source()->size() + 1 : 0;
6746 case GL_COMPILE_STATUS:
6747 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6749 case GL_INFO_LOG_LENGTH:
6750 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6752 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6753 *params = shader->translated_source() ?
6754 shader->translated_source()->size() + 1 : 0;
6759 glGetShaderiv(shader->service_id(), pname, params);
6762 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6763 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6764 GLuint shader_id = c.shader;
6765 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6766 Bucket* bucket = CreateBucket(bucket_id);
6767 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6768 if (!shader || !shader->source()) {
6770 return error::kNoError;
6772 bucket->SetFromString(shader->source()->c_str());
6773 return error::kNoError;
6776 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6777 uint32 immediate_data_size,
6778 const cmds::GetTranslatedShaderSourceANGLE& c) {
6779 GLuint shader_id = c.shader;
6780 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6781 Bucket* bucket = CreateBucket(bucket_id);
6782 Shader* shader = GetShaderInfoNotProgram(
6783 shader_id, "glGetTranslatedShaderSourceANGLE");
6786 return error::kNoError;
6789 bucket->SetFromString(shader->translated_source() ?
6790 shader->translated_source()->c_str() : NULL);
6791 return error::kNoError;
6794 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6795 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6796 GLuint program_id = c.program;
6797 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6798 Bucket* bucket = CreateBucket(bucket_id);
6799 Program* program = GetProgramInfoNotShader(
6800 program_id, "glGetProgramInfoLog");
6801 if (!program || !program->log_info()) {
6802 bucket->SetFromString("");
6803 return error::kNoError;
6805 bucket->SetFromString(program->log_info()->c_str());
6806 return error::kNoError;
6809 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6810 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6811 GLuint shader_id = c.shader;
6812 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6813 Bucket* bucket = CreateBucket(bucket_id);
6814 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6815 if (!shader || !shader->log_info()) {
6816 bucket->SetFromString("");
6817 return error::kNoError;
6819 bucket->SetFromString(shader->log_info()->c_str());
6820 return error::kNoError;
6823 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6824 return state_.GetEnabled(cap);
6827 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6828 const Buffer* buffer = GetBuffer(client_id);
6829 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6832 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6833 const Framebuffer* framebuffer =
6834 GetFramebuffer(client_id);
6835 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6838 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6839 // IsProgram is true for programs as soon as they are created, until they are
6840 // deleted and no longer in use.
6841 const Program* program = GetProgram(client_id);
6842 return program != NULL && !program->IsDeleted();
6845 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6846 const Renderbuffer* renderbuffer =
6847 GetRenderbuffer(client_id);
6848 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6851 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6852 // IsShader is true for shaders as soon as they are created, until they
6853 // are deleted and not attached to any programs.
6854 const Shader* shader = GetShader(client_id);
6855 return shader != NULL && !shader->IsDeleted();
6858 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6859 const TextureRef* texture_ref = GetTexture(client_id);
6860 return texture_ref && texture_ref->texture()->IsValid();
6863 void GLES2DecoderImpl::DoAttachShader(
6864 GLuint program_client_id, GLint shader_client_id) {
6865 Program* program = GetProgramInfoNotShader(
6866 program_client_id, "glAttachShader");
6870 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6874 if (!program->AttachShader(shader_manager(), shader)) {
6876 GL_INVALID_OPERATION,
6878 "can not attach more than one shader of the same type.");
6881 glAttachShader(program->service_id(), shader->service_id());
6884 void GLES2DecoderImpl::DoDetachShader(
6885 GLuint program_client_id, GLint shader_client_id) {
6886 Program* program = GetProgramInfoNotShader(
6887 program_client_id, "glDetachShader");
6891 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6895 if (!program->DetachShader(shader_manager(), shader)) {
6897 GL_INVALID_OPERATION,
6898 "glDetachShader", "shader not attached to program");
6901 glDetachShader(program->service_id(), shader->service_id());
6904 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6905 Program* program = GetProgramInfoNotShader(
6906 program_client_id, "glValidateProgram");
6910 program->Validate();
6913 void GLES2DecoderImpl::GetVertexAttribHelper(
6914 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6916 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6917 Buffer* buffer = attrib->buffer();
6918 if (buffer && !buffer->IsDeleted()) {
6920 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6921 *params = client_id;
6925 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6926 *params = attrib->enabled();
6928 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6929 *params = attrib->size();
6931 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6932 *params = attrib->gl_stride();
6934 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6935 *params = attrib->type();
6937 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6938 *params = attrib->normalized();
6940 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6941 *params = attrib->divisor();
6949 void GLES2DecoderImpl::DoGetTexParameterfv(
6950 GLenum target, GLenum pname, GLfloat* params) {
6951 InitTextureMaxAnisotropyIfNeeded(target, pname);
6952 glGetTexParameterfv(target, pname, params);
6955 void GLES2DecoderImpl::DoGetTexParameteriv(
6956 GLenum target, GLenum pname, GLint* params) {
6957 InitTextureMaxAnisotropyIfNeeded(target, pname);
6958 glGetTexParameteriv(target, pname, params);
6961 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
6962 GLenum target, GLenum pname) {
6963 if (!workarounds().init_texture_max_anisotropy)
6965 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
6966 !validators_->texture_parameter.IsValid(pname)) {
6970 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
6974 GL_INVALID_OPERATION,
6975 "glGetTexParamter{fi}v", "unknown texture for target");
6978 Texture* texture = texture_ref->texture();
6979 texture->InitTextureMaxAnisotropyIfNeeded(target);
6982 void GLES2DecoderImpl::DoGetVertexAttribfv(
6983 GLuint index, GLenum pname, GLfloat* params) {
6984 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6987 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6991 case GL_CURRENT_VERTEX_ATTRIB: {
6992 const Vec4& value = state_.attrib_values[index];
6993 params[0] = value.v[0];
6994 params[1] = value.v[1];
6995 params[2] = value.v[2];
6996 params[3] = value.v[3];
7001 GetVertexAttribHelper(attrib, pname, &value);
7002 *params = static_cast<GLfloat>(value);
7008 void GLES2DecoderImpl::DoGetVertexAttribiv(
7009 GLuint index, GLenum pname, GLint* params) {
7010 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7013 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7017 case GL_CURRENT_VERTEX_ATTRIB: {
7018 const Vec4& value = state_.attrib_values[index];
7019 params[0] = static_cast<GLint>(value.v[0]);
7020 params[1] = static_cast<GLint>(value.v[1]);
7021 params[2] = static_cast<GLint>(value.v[2]);
7022 params[3] = static_cast<GLint>(value.v[3]);
7026 GetVertexAttribHelper(attrib, pname, params);
7031 bool GLES2DecoderImpl::SetVertexAttribValue(
7032 const char* function_name, GLuint index, const GLfloat* value) {
7033 if (index >= state_.attrib_values.size()) {
7034 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7037 Vec4& v = state_.attrib_values[index];
7045 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7046 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7047 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7048 glVertexAttrib1f(index, v0);
7052 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7053 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7054 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7055 glVertexAttrib2f(index, v0, v1);
7059 void GLES2DecoderImpl::DoVertexAttrib3f(
7060 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7061 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7062 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7063 glVertexAttrib3f(index, v0, v1, v2);
7067 void GLES2DecoderImpl::DoVertexAttrib4f(
7068 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7069 GLfloat v[4] = { v0, v1, v2, v3, };
7070 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7071 glVertexAttrib4f(index, v0, v1, v2, v3);
7075 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7076 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7077 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7078 glVertexAttrib1fv(index, v);
7082 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7083 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7084 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7085 glVertexAttrib2fv(index, v);
7089 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7090 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7091 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7092 glVertexAttrib3fv(index, v);
7096 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7097 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7098 glVertexAttrib4fv(index, v);
7102 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7103 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
7105 if (!state_.bound_array_buffer.get() ||
7106 state_.bound_array_buffer->IsDeleted()) {
7107 if (state_.vertex_attrib_manager.get() ==
7108 state_.default_vertex_attrib_manager.get()) {
7110 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7111 return error::kNoError;
7112 } else if (c.offset != 0) {
7115 "glVertexAttribPointer", "client side arrays are not allowed");
7116 return error::kNoError;
7120 GLuint indx = c.indx;
7121 GLint size = c.size;
7122 GLenum type = c.type;
7123 GLboolean normalized = c.normalized;
7124 GLsizei stride = c.stride;
7125 GLsizei offset = c.offset;
7126 const void* ptr = reinterpret_cast<const void*>(offset);
7127 if (!validators_->vertex_attrib_type.IsValid(type)) {
7128 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7129 return error::kNoError;
7131 if (!validators_->vertex_attrib_size.IsValid(size)) {
7133 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7134 return error::kNoError;
7136 if (indx >= group_->max_vertex_attribs()) {
7138 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7139 return error::kNoError;
7143 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7144 return error::kNoError;
7148 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7149 return error::kNoError;
7153 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7154 return error::kNoError;
7156 GLsizei component_size =
7157 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7158 if (offset % component_size > 0) {
7160 GL_INVALID_OPERATION,
7161 "glVertexAttribPointer", "offset not valid for type");
7162 return error::kNoError;
7164 if (stride % component_size > 0) {
7166 GL_INVALID_OPERATION,
7167 "glVertexAttribPointer", "stride not valid for type");
7168 return error::kNoError;
7170 state_.vertex_attrib_manager
7171 ->SetAttribInfo(indx,
7172 state_.bound_array_buffer.get(),
7177 stride != 0 ? stride : component_size * size,
7179 if (type != GL_FIXED) {
7180 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7182 return error::kNoError;
7185 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7187 state_.viewport_x = x;
7188 state_.viewport_y = y;
7189 state_.viewport_width = std::min(width, viewport_max_width_);
7190 state_.viewport_height = std::min(height, viewport_max_height_);
7191 glViewport(x, y, width, height);
7194 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7195 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7196 if (!features().angle_instanced_arrays) {
7198 GL_INVALID_OPERATION,
7199 "glVertexAttribDivisorANGLE", "function not available");
7201 GLuint index = c.index;
7202 GLuint divisor = c.divisor;
7203 if (index >= group_->max_vertex_attribs()) {
7206 "glVertexAttribDivisorANGLE", "index out of range");
7207 return error::kNoError;
7210 state_.vertex_attrib_manager->SetDivisor(
7213 glVertexAttribDivisorANGLE(index, divisor);
7214 return error::kNoError;
7217 template <typename pixel_data_type>
7218 static void WriteAlphaData(
7219 void *pixels, uint32 row_count, uint32 channel_count,
7220 uint32 alpha_channel_index, uint32 unpadded_row_size,
7221 uint32 padded_row_size, pixel_data_type alpha_value) {
7222 DCHECK_GT(channel_count, 0U);
7223 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7224 uint32 unpadded_row_size_in_elements =
7225 unpadded_row_size / sizeof(pixel_data_type);
7226 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7227 uint32 padded_row_size_in_elements =
7228 padded_row_size / sizeof(pixel_data_type);
7229 pixel_data_type* dst =
7230 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7231 for (uint32 yy = 0; yy < row_count; ++yy) {
7232 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7233 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7236 dst += padded_row_size_in_elements;
7240 void GLES2DecoderImpl::FinishReadPixels(
7241 const cmds::ReadPixels& c,
7243 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7244 GLsizei width = c.width;
7245 GLsizei height = c.height;
7246 GLenum format = c.format;
7247 GLenum type = c.type;
7248 typedef cmds::ReadPixels::Result Result;
7250 Result* result = NULL;
7251 if (c.result_shm_id != 0) {
7252 result = GetSharedMemoryAs<Result*>(
7253 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7256 glDeleteBuffersARB(1, &buffer);
7261 GLES2Util::ComputeImageDataSizes(
7262 width, height, format, type, state_.pack_alignment, &pixels_size,
7264 void* pixels = GetSharedMemoryAs<void*>(
7265 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7268 glDeleteBuffersARB(1, &buffer);
7274 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7276 if (features().map_buffer_range) {
7277 data = glMapBufferRange(
7278 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7280 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7282 memcpy(pixels, data, pixels_size);
7283 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7284 // have to restore the state.
7285 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7286 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7287 glDeleteBuffersARB(1, &buffer);
7290 if (result != NULL) {
7294 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7295 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7296 if ((channels_exist & 0x0008) == 0 &&
7297 workarounds().clear_alpha_in_readpixels) {
7298 // Set the alpha to 255 because some drivers are buggy in this regard.
7301 uint32 unpadded_row_size;
7302 uint32 padded_row_size;
7303 if (!GLES2Util::ComputeImageDataSizes(
7304 width, 2, format, type, state_.pack_alignment, &temp_size,
7305 &unpadded_row_size, &padded_row_size)) {
7309 uint32 channel_count = 0;
7310 uint32 alpha_channel = 0;
7323 if (channel_count > 0) {
7325 case GL_UNSIGNED_BYTE:
7326 WriteAlphaData<uint8>(
7327 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7328 padded_row_size, 0xFF);
7331 WriteAlphaData<float>(
7332 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7333 padded_row_size, 1.0f);
7336 WriteAlphaData<uint16>(
7337 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7338 padded_row_size, 0x3C00);
7346 error::Error GLES2DecoderImpl::HandleReadPixels(
7347 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7348 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7349 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7350 if (fbo_error != error::kNoError)
7354 GLsizei width = c.width;
7355 GLsizei height = c.height;
7356 GLenum format = c.format;
7357 GLenum type = c.type;
7358 GLboolean async = c.async;
7359 if (width < 0 || height < 0) {
7360 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7361 return error::kNoError;
7363 typedef cmds::ReadPixels::Result Result;
7365 if (!GLES2Util::ComputeImageDataSizes(
7366 width, height, format, type, state_.pack_alignment, &pixels_size,
7368 return error::kOutOfBounds;
7370 void* pixels = GetSharedMemoryAs<void*>(
7371 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7373 return error::kOutOfBounds;
7375 Result* result = NULL;
7376 if (c.result_shm_id != 0) {
7377 result = GetSharedMemoryAs<Result*>(
7378 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7380 return error::kOutOfBounds;
7384 if (!validators_->read_pixel_format.IsValid(format)) {
7385 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7386 return error::kNoError;
7388 if (!validators_->read_pixel_type.IsValid(type)) {
7389 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7390 return error::kNoError;
7392 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7393 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7394 // format and type are acceptable enums but not guaranteed to be supported
7395 // for this framebuffer. Have to ask gl if they are valid.
7396 GLint preferred_format = 0;
7397 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7398 GLint preferred_type = 0;
7399 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7400 if (format != static_cast<GLenum>(preferred_format) ||
7401 type != static_cast<GLenum>(preferred_type)) {
7403 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7404 "with the current read framebuffer");
7405 return error::kNoError;
7408 if (width == 0 || height == 0) {
7409 return error::kNoError;
7412 // Get the size of the current fbo or backbuffer.
7413 gfx::Size max_size = GetBoundReadFrameBufferSize();
7417 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7419 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7420 return error::kNoError;
7423 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7424 return error::kNoError;
7427 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7429 ScopedResolvedFrameBufferBinder binder(this, false, true);
7431 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7432 // The user requested an out of range area. Get the results 1 line
7435 uint32 unpadded_row_size;
7436 uint32 padded_row_size;
7437 if (!GLES2Util::ComputeImageDataSizes(
7438 width, 2, format, type, state_.pack_alignment, &temp_size,
7439 &unpadded_row_size, &padded_row_size)) {
7441 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7442 return error::kNoError;
7445 GLint dest_x_offset = std::max(-x, 0);
7446 uint32 dest_row_offset;
7447 if (!GLES2Util::ComputeImageDataSizes(
7448 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7451 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7452 return error::kNoError;
7455 // Copy each row into the larger dest rect.
7456 int8* dst = static_cast<int8*>(pixels);
7457 GLint read_x = std::max(0, x);
7458 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7459 GLint read_width = read_end_x - read_x;
7460 for (GLint yy = 0; yy < height; ++yy) {
7464 memset(dst, 0, unpadded_row_size);
7466 // If the row is in range, copy it.
7467 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7469 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7471 dst += padded_row_size;
7474 if (async && features().use_async_readpixels) {
7476 glGenBuffersARB(1, &buffer);
7477 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7478 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7479 GLenum error = glGetError();
7480 if (error == GL_NO_ERROR) {
7481 glReadPixels(x, y, width, height, format, type, 0);
7482 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7483 new FenceCallback()));
7484 WaitForReadPixels(base::Bind(
7485 &GLES2DecoderImpl::FinishReadPixels,
7486 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7487 <GLES2DecoderImpl>(this),
7489 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7490 return error::kNoError;
7492 // On error, unbind pack buffer and fall through to sync readpixels
7493 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7496 glReadPixels(x, y, width, height, format, type, pixels);
7498 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7499 if (error == GL_NO_ERROR) {
7500 if (result != NULL) {
7503 FinishReadPixels(c, 0);
7506 return error::kNoError;
7509 error::Error GLES2DecoderImpl::HandlePixelStorei(
7510 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7511 GLenum pname = c.pname;
7512 GLenum param = c.param;
7513 if (!validators_->pixel_store.IsValid(pname)) {
7514 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7515 return error::kNoError;
7518 case GL_PACK_ALIGNMENT:
7519 case GL_UNPACK_ALIGNMENT:
7520 if (!validators_->pixel_store_alignment.IsValid(param)) {
7522 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7523 return error::kNoError;
7526 case GL_UNPACK_FLIP_Y_CHROMIUM:
7527 unpack_flip_y_ = (param != 0);
7528 return error::kNoError;
7529 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7530 unpack_premultiply_alpha_ = (param != 0);
7531 return error::kNoError;
7532 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7533 unpack_unpremultiply_alpha_ = (param != 0);
7534 return error::kNoError;
7538 glPixelStorei(pname, param);
7540 case GL_PACK_ALIGNMENT:
7541 state_.pack_alignment = param;
7543 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7544 state_.pack_reverse_row_order = (param != 0);
7546 case GL_UNPACK_ALIGNMENT:
7547 state_.unpack_alignment = param;
7550 // Validation should have prevented us from getting here.
7554 return error::kNoError;
7557 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7558 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7559 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7561 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7563 if (!supports_post_sub_buffer_) {
7565 GL_INVALID_OPERATION,
7566 "glPostSubBufferCHROMIUM", "command not supported by surface");
7567 return error::kNoError;
7570 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7573 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7574 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7575 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7576 is_offscreen ? offscreen_size_ : surface_->GetSize());
7578 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7579 return error::kNoError;
7581 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7582 return error::kLostContext;
7586 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7587 uint32 immediate_data_size,
7588 const cmds::ScheduleOverlayPlaneCHROMIUM& c) {
7589 NOTIMPLEMENTED() << "Overlay supported isn't finished.";
7590 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
7591 "glScheduleOverlayPlaneCHROMIUM",
7592 "function not implemented");
7593 return error::kNoError;
7596 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7597 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7598 const std::string& name_str) {
7599 if (!StringIsValidForGLES(name_str.c_str())) {
7601 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7602 return error::kNoError;
7604 Program* program = GetProgramInfoNotShader(
7605 client_id, "glGetAttribLocation");
7607 return error::kNoError;
7609 if (!program->IsValid()) {
7611 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7612 return error::kNoError;
7614 GLint* location = GetSharedMemoryAs<GLint*>(
7615 location_shm_id, location_shm_offset, sizeof(GLint));
7617 return error::kOutOfBounds;
7619 // Require the client to init this incase the context is lost and we are no
7620 // longer executing commands.
7621 if (*location != -1) {
7622 return error::kGenericError;
7624 *location = program->GetAttribLocation(name_str);
7625 return error::kNoError;
7628 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7629 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7630 uint32 name_size = c.data_size;
7631 const char* name = GetSharedMemoryAs<const char*>(
7632 c.name_shm_id, c.name_shm_offset, name_size);
7634 return error::kOutOfBounds;
7636 std::string name_str(name, name_size);
7637 return GetAttribLocationHelper(
7638 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7641 error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
7642 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
7643 Bucket* bucket = GetBucket(c.name_bucket_id);
7645 return error::kInvalidArguments;
7647 std::string name_str;
7648 if (!bucket->GetAsString(&name_str)) {
7649 return error::kInvalidArguments;
7651 return GetAttribLocationHelper(
7652 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7655 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7656 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7657 const std::string& name_str) {
7658 if (!StringIsValidForGLES(name_str.c_str())) {
7660 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7661 return error::kNoError;
7663 Program* program = GetProgramInfoNotShader(
7664 client_id, "glGetUniformLocation");
7666 return error::kNoError;
7668 if (!program->IsValid()) {
7670 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7671 return error::kNoError;
7673 GLint* location = GetSharedMemoryAs<GLint*>(
7674 location_shm_id, location_shm_offset, sizeof(GLint));
7676 return error::kOutOfBounds;
7678 // Require the client to init this incase the context is lost an we are no
7679 // longer executing commands.
7680 if (*location != -1) {
7681 return error::kGenericError;
7683 *location = program->GetUniformFakeLocation(name_str);
7684 return error::kNoError;
7687 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7688 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7689 uint32 name_size = c.data_size;
7690 const char* name = GetSharedMemoryAs<const char*>(
7691 c.name_shm_id, c.name_shm_offset, name_size);
7693 return error::kOutOfBounds;
7695 std::string name_str(name, name_size);
7696 return GetUniformLocationHelper(
7697 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7700 error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
7701 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
7702 Bucket* bucket = GetBucket(c.name_bucket_id);
7704 return error::kInvalidArguments;
7706 std::string name_str;
7707 if (!bucket->GetAsString(&name_str)) {
7708 return error::kInvalidArguments;
7710 return GetUniformLocationHelper(
7711 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7714 error::Error GLES2DecoderImpl::HandleGetString(
7715 uint32 immediate_data_size, const cmds::GetString& c) {
7716 GLenum name = static_cast<GLenum>(c.name);
7717 if (!validators_->string_type.IsValid(name)) {
7718 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7719 return error::kNoError;
7721 const char* str = reinterpret_cast<const char*>(glGetString(name));
7722 std::string extensions;
7725 str = "OpenGL ES 2.0 Chromium";
7727 case GL_SHADING_LANGUAGE_VERSION:
7728 str = "OpenGL ES GLSL ES 1.0 Chromium";
7732 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7733 // They are used by WEBGL_debug_renderer_info.
7734 if (!force_webgl_glsl_validation_)
7739 // For WebGL contexts, strip out the OES derivatives and
7740 // EXT frag depth extensions if they have not been enabled.
7741 if (force_webgl_glsl_validation_) {
7742 extensions = feature_info_->extensions();
7743 if (!derivatives_explicitly_enabled_) {
7744 size_t offset = extensions.find(kOESDerivativeExtension);
7745 if (std::string::npos != offset) {
7746 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7750 if (!frag_depth_explicitly_enabled_) {
7751 size_t offset = extensions.find(kEXTFragDepthExtension);
7752 if (std::string::npos != offset) {
7753 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7757 if (!draw_buffers_explicitly_enabled_) {
7758 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7759 if (std::string::npos != offset) {
7760 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7764 if (!shader_texture_lod_explicitly_enabled_) {
7765 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
7766 if (std::string::npos != offset) {
7767 extensions.replace(offset,
7768 arraysize(kEXTShaderTextureLodExtension),
7773 extensions = feature_info_->extensions().c_str();
7775 if (supports_post_sub_buffer_)
7776 extensions += " GL_CHROMIUM_post_sub_buffer";
7777 str = extensions.c_str();
7783 Bucket* bucket = CreateBucket(c.bucket_id);
7784 bucket->SetFromString(str);
7785 return error::kNoError;
7788 error::Error GLES2DecoderImpl::HandleBufferData(
7789 uint32 immediate_data_size, const cmds::BufferData& c) {
7790 GLenum target = static_cast<GLenum>(c.target);
7791 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7792 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7793 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7794 GLenum usage = static_cast<GLenum>(c.usage);
7795 const void* data = NULL;
7796 if (data_shm_id != 0 || data_shm_offset != 0) {
7797 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7799 return error::kOutOfBounds;
7802 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7803 return error::kNoError;
7806 void GLES2DecoderImpl::DoBufferSubData(
7807 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7808 // Just delegate it. Some validation is actually done before this.
7809 buffer_manager()->ValidateAndDoBufferSubData(
7810 &state_, target, offset, size, data);
7813 bool GLES2DecoderImpl::ClearLevel(
7814 unsigned service_id,
7815 unsigned bind_target,
7818 unsigned internal_format,
7823 bool is_texture_immutable) {
7824 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7825 if (feature_info_->feature_flags().angle_depth_texture &&
7826 (channels & GLES2Util::kDepth) != 0) {
7827 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7828 // on depth formats.
7830 glGenFramebuffersEXT(1, &fb);
7831 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7833 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7834 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7835 GL_DEPTH_ATTACHMENT;
7837 glFramebufferTexture2DEXT(
7838 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7839 // ANGLE promises a depth only attachment ok.
7840 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7841 GL_FRAMEBUFFER_COMPLETE) {
7847 state_.SetDeviceDepthMask(GL_TRUE);
7848 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
7849 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7851 RestoreClearState();
7853 glDeleteFramebuffersEXT(1, &fb);
7854 Framebuffer* framebuffer =
7855 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7856 GLuint fb_service_id =
7857 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7858 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7862 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7865 uint32 padded_row_size;
7866 if (!GLES2Util::ComputeImageDataSizes(
7867 width, height, format, type, state_.unpack_alignment, &size,
7868 NULL, &padded_row_size)) {
7872 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7876 if (size > kMaxZeroSize) {
7877 if (kMaxZeroSize < padded_row_size) {
7878 // That'd be an awfully large texture.
7881 // We should never have a large total size with a zero row size.
7882 DCHECK_GT(padded_row_size, 0U);
7883 tile_height = kMaxZeroSize / padded_row_size;
7884 if (!GLES2Util::ComputeImageDataSizes(
7885 width, tile_height, format, type, state_.unpack_alignment, &size,
7890 tile_height = height;
7893 // Assumes the size has already been checked.
7894 scoped_ptr<char[]> zero(new char[size]);
7895 memset(zero.get(), 0, size);
7896 glBindTexture(bind_target, service_id);
7899 while (y < height) {
7900 GLint h = y + tile_height > height ? height - y : tile_height;
7901 if (is_texture_immutable || h != height) {
7902 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7905 target, level, internal_format, width, h, 0, format, type,
7910 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7911 &state_, bind_target);
7912 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7918 const int kS3TCBlockWidth = 4;
7919 const int kS3TCBlockHeight = 4;
7920 const int kS3TCDXT1BlockSize = 8;
7921 const int kS3TCDXT3AndDXT5BlockSize = 16;
7923 bool IsValidDXTSize(GLint level, GLsizei size) {
7924 return (size == 1) ||
7925 (size == 2) || !(size % kS3TCBlockWidth);
7928 bool IsValidPVRTCSize(GLint level, GLsizei size) {
7929 // Ensure that the size is a power of two
7930 return (size & (size - 1)) == 0;
7933 } // anonymous namespace.
7935 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7936 const char* function_name,
7937 GLsizei width, GLsizei height, GLenum format, size_t size) {
7938 unsigned int bytes_required = 0;
7941 case GL_ATC_RGB_AMD:
7942 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7943 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7944 case GL_ETC1_RGB8_OES: {
7945 int num_blocks_across =
7946 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7947 int num_blocks_down =
7948 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7949 int num_blocks = num_blocks_across * num_blocks_down;
7950 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7953 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
7954 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
7955 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7956 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7957 int num_blocks_across =
7958 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7959 int num_blocks_down =
7960 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7961 int num_blocks = num_blocks_across * num_blocks_down;
7962 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7965 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
7966 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
7967 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
7970 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
7971 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
7972 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
7976 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7980 if (size != bytes_required) {
7982 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7989 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7990 const char* function_name,
7991 GLint level, GLsizei width, GLsizei height, GLenum format) {
7993 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7994 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7995 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7996 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7997 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7999 GL_INVALID_OPERATION, function_name,
8000 "width or height invalid for level");
8005 case GL_ATC_RGB_AMD:
8006 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8007 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8008 case GL_ETC1_RGB8_OES: {
8009 if (width <= 0 || height <= 0) {
8011 GL_INVALID_OPERATION, function_name,
8012 "width or height invalid for level");
8017 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8018 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8019 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8020 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8021 if (!IsValidPVRTCSize(level, width) ||
8022 !IsValidPVRTCSize(level, height)) {
8024 GL_INVALID_OPERATION, function_name,
8025 "width or height invalid for level");
8035 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8036 const char* function_name,
8037 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8038 GLsizei width, GLsizei height, GLenum format,
8040 if (xoffset < 0 || yoffset < 0) {
8042 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8047 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8048 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8049 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8050 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8051 const int kBlockWidth = 4;
8052 const int kBlockHeight = 4;
8053 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8055 GL_INVALID_OPERATION, function_name,
8056 "xoffset or yoffset not multiple of 4");
8059 GLsizei tex_width = 0;
8060 GLsizei tex_height = 0;
8061 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8062 width - xoffset > tex_width ||
8063 height - yoffset > tex_height) {
8065 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8068 return ValidateCompressedTexDimensions(
8069 function_name, level, width, height, format);
8071 case GL_ATC_RGB_AMD:
8072 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8073 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8075 GL_INVALID_OPERATION, function_name,
8076 "not supported for ATC textures");
8079 case GL_ETC1_RGB8_OES: {
8081 GL_INVALID_OPERATION, function_name,
8082 "not supported for ECT1_RGB8_OES textures");
8085 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8086 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8087 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8088 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8089 if ((xoffset != 0) || (yoffset != 0)) {
8091 GL_INVALID_OPERATION, function_name,
8092 "xoffset and yoffset must be zero");
8095 GLsizei tex_width = 0;
8096 GLsizei tex_height = 0;
8097 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8098 width != tex_width ||
8099 height != tex_height) {
8101 GL_INVALID_OPERATION, function_name,
8102 "dimensions must match existing texture level dimensions");
8105 return ValidateCompressedTexDimensions(
8106 function_name, level, width, height, format);
8113 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8116 GLenum internal_format,
8122 // TODO(gman): Validate image_size is correct for width, height and format.
8123 if (!validators_->texture_target.IsValid(target)) {
8124 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8125 "glCompressedTexImage2D", target, "target");
8126 return error::kNoError;
8128 if (!validators_->compressed_texture_format.IsValid(
8130 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8131 "glCompressedTexImage2D", internal_format, "internal_format");
8132 return error::kNoError;
8134 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8138 "glCompressedTexImage2D", "dimensions out of range");
8139 return error::kNoError;
8141 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8146 "glCompressedTexImage2D", "unknown texture target");
8147 return error::kNoError;
8149 Texture* texture = texture_ref->texture();
8150 if (texture->IsImmutable()) {
8152 GL_INVALID_OPERATION,
8153 "glCompressedTexImage2D", "texture is immutable");
8154 return error::kNoError;
8157 if (!ValidateCompressedTexDimensions(
8158 "glCompressedTexImage2D", level, width, height, internal_format) ||
8159 !ValidateCompressedTexFuncData(
8160 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8161 return error::kNoError;
8164 if (!EnsureGPUMemoryAvailable(image_size)) {
8166 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8167 return error::kNoError;
8170 if (texture->IsAttachedToFramebuffer()) {
8171 framebuffer_state_.clear_state_dirty = true;
8174 scoped_ptr<int8[]> zero;
8176 zero.reset(new int8[image_size]);
8177 memset(zero.get(), 0, image_size);
8180 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8181 glCompressedTexImage2D(
8182 target, level, internal_format, width, height, border, image_size, data);
8183 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8184 if (error == GL_NO_ERROR) {
8185 texture_manager()->SetLevelInfo(
8186 texture_ref, target, level, internal_format,
8187 width, height, 1, border, 0, 0, true);
8189 return error::kNoError;
8192 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8193 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
8194 GLenum target = static_cast<GLenum>(c.target);
8195 GLint level = static_cast<GLint>(c.level);
8196 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8197 GLsizei width = static_cast<GLsizei>(c.width);
8198 GLsizei height = static_cast<GLsizei>(c.height);
8199 GLint border = static_cast<GLint>(c.border);
8200 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8201 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8202 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8203 const void* data = NULL;
8204 if (data_shm_id != 0 || data_shm_offset != 0) {
8205 data = GetSharedMemoryAs<const void*>(
8206 data_shm_id, data_shm_offset, image_size);
8208 return error::kOutOfBounds;
8211 return DoCompressedTexImage2D(
8212 target, level, internal_format, width, height, border, image_size, data);
8215 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8216 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
8217 GLenum target = static_cast<GLenum>(c.target);
8218 GLint level = static_cast<GLint>(c.level);
8219 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8220 GLsizei width = static_cast<GLsizei>(c.width);
8221 GLsizei height = static_cast<GLsizei>(c.height);
8222 GLint border = static_cast<GLint>(c.border);
8223 Bucket* bucket = GetBucket(c.bucket_id);
8225 return error::kInvalidArguments;
8227 uint32 data_size = bucket->size();
8228 GLsizei imageSize = data_size;
8229 const void* data = bucket->GetData(0, data_size);
8231 return error::kInvalidArguments;
8233 return DoCompressedTexImage2D(
8234 target, level, internal_format, width, height, border,
8238 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8239 uint32 immediate_data_size,
8240 const cmds::CompressedTexSubImage2DBucket& c) {
8241 GLenum target = static_cast<GLenum>(c.target);
8242 GLint level = static_cast<GLint>(c.level);
8243 GLint xoffset = static_cast<GLint>(c.xoffset);
8244 GLint yoffset = static_cast<GLint>(c.yoffset);
8245 GLsizei width = static_cast<GLsizei>(c.width);
8246 GLsizei height = static_cast<GLsizei>(c.height);
8247 GLenum format = static_cast<GLenum>(c.format);
8248 Bucket* bucket = GetBucket(c.bucket_id);
8250 return error::kInvalidArguments;
8252 uint32 data_size = bucket->size();
8253 GLsizei imageSize = data_size;
8254 const void* data = bucket->GetData(0, data_size);
8256 return error::kInvalidArguments;
8258 if (!validators_->texture_target.IsValid(target)) {
8260 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8261 return error::kNoError;
8263 if (!validators_->compressed_texture_format.IsValid(format)) {
8264 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8265 "glCompressedTexSubImage2D", format, "format");
8266 return error::kNoError;
8270 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8271 return error::kNoError;
8275 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8276 return error::kNoError;
8278 if (imageSize < 0) {
8280 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8281 return error::kNoError;
8283 DoCompressedTexSubImage2D(
8284 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8285 return error::kNoError;
8288 error::Error GLES2DecoderImpl::HandleTexImage2D(
8289 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8290 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
8291 // Set as failed for now, but if it successed, this will be set to not failed.
8292 texture_state_.tex_image_2d_failed = true;
8293 GLenum target = static_cast<GLenum>(c.target);
8294 GLint level = static_cast<GLint>(c.level);
8295 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8296 // for internalformat.
8297 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8298 GLsizei width = static_cast<GLsizei>(c.width);
8299 GLsizei height = static_cast<GLsizei>(c.height);
8300 GLint border = static_cast<GLint>(c.border);
8301 GLenum format = static_cast<GLenum>(c.format);
8302 GLenum type = static_cast<GLenum>(c.type);
8303 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8304 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8306 if (!GLES2Util::ComputeImageDataSizes(
8307 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8309 return error::kOutOfBounds;
8311 const void* pixels = NULL;
8312 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8313 pixels = GetSharedMemoryAs<const void*>(
8314 pixels_shm_id, pixels_shm_offset, pixels_size);
8316 return error::kOutOfBounds;
8320 TextureManager::DoTextImage2DArguments args = {
8321 target, level, internal_format, width, height, border, format, type,
8322 pixels, pixels_size};
8323 texture_manager()->ValidateAndDoTexImage2D(
8324 &texture_state_, &state_, &framebuffer_state_, args);
8325 return error::kNoError;
8328 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8337 const void * data) {
8338 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8342 GL_INVALID_OPERATION,
8343 "glCompressedTexSubImage2D", "unknown texture for target");
8346 Texture* texture = texture_ref->texture();
8348 GLenum internal_format = 0;
8349 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8351 GL_INVALID_OPERATION,
8352 "glCompressedTexSubImage2D", "level does not exist.");
8355 if (internal_format != format) {
8357 GL_INVALID_OPERATION,
8358 "glCompressedTexSubImage2D", "format does not match internal format.");
8361 if (!texture->ValidForTexture(
8362 target, level, xoffset, yoffset, width, height, type)) {
8364 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8368 if (!ValidateCompressedTexFuncData(
8369 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8370 !ValidateCompressedTexSubDimensions(
8371 "glCompressedTexSubImage2D",
8372 target, level, xoffset, yoffset, width, height, format, texture)) {
8377 // Note: There is no need to deal with texture cleared tracking here
8378 // because the validation above means you can only get here if the level
8379 // is already a matching compressed format and in that case
8380 // CompressedTexImage2D already cleared the texture.
8381 glCompressedTexSubImage2D(
8382 target, level, xoffset, yoffset, width, height, format, image_size, data);
8386 GLint start, GLint range, GLint sourceRange,
8387 GLint* out_start, GLint* out_range) {
8394 GLint end = start + range;
8395 if (end > sourceRange) {
8396 range -= end - sourceRange;
8402 void GLES2DecoderImpl::DoCopyTexImage2D(
8405 GLenum internal_format,
8411 DCHECK(!ShouldDeferReads());
8412 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8416 GL_INVALID_OPERATION,
8417 "glCopyTexImage2D", "unknown texture for target");
8420 Texture* texture = texture_ref->texture();
8421 if (texture->IsImmutable()) {
8423 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8425 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8428 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8431 if (!texture_manager()->ValidateFormatAndTypeCombination(
8432 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8433 GL_UNSIGNED_BYTE)) {
8437 // Check we have compatible formats.
8438 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8439 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8440 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8442 if ((channels_needed & channels_exist) != channels_needed) {
8444 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8448 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8450 GL_INVALID_OPERATION,
8451 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8455 uint32 estimated_size = 0;
8456 if (!GLES2Util::ComputeImageDataSizes(
8457 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8458 &estimated_size, NULL, NULL)) {
8460 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8464 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8465 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8469 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8473 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8474 ScopedResolvedFrameBufferBinder binder(this, false, true);
8475 gfx::Size size = GetBoundReadFrameBufferSize();
8477 if (texture->IsAttachedToFramebuffer()) {
8478 framebuffer_state_.clear_state_dirty = true;
8481 // Clip to size to source dimensions
8484 GLint copyWidth = 0;
8485 GLint copyHeight = 0;
8486 Clip(x, width, size.width(), ©X, ©Width);
8487 Clip(y, height, size.height(), ©Y, ©Height);
8491 copyWidth != width ||
8492 copyHeight != height) {
8493 // some part was clipped so clear the texture.
8495 texture->service_id(), texture->target(),
8496 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8497 width, height, texture->IsImmutable())) {
8499 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8502 if (copyHeight > 0 && copyWidth > 0) {
8503 GLint dx = copyX - x;
8504 GLint dy = copyY - y;
8507 ScopedModifyPixels modify(texture_ref);
8508 glCopyTexSubImage2D(target, level,
8509 destX, destY, copyX, copyY,
8510 copyWidth, copyHeight);
8513 ScopedModifyPixels modify(texture_ref);
8514 glCopyTexImage2D(target, level, internal_format,
8515 copyX, copyY, copyWidth, copyHeight, border);
8517 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8518 if (error == GL_NO_ERROR) {
8519 texture_manager()->SetLevelInfo(
8520 texture_ref, target, level, internal_format, width, height, 1,
8521 border, internal_format, GL_UNSIGNED_BYTE, true);
8525 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8534 DCHECK(!ShouldDeferReads());
8535 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8539 GL_INVALID_OPERATION,
8540 "glCopyTexSubImage2D", "unknown texture for target");
8543 Texture* texture = texture_ref->texture();
8546 if (!texture->GetLevelType(target, level, &type, &format) ||
8547 !texture->ValidForTexture(
8548 target, level, xoffset, yoffset, width, height, type)) {
8550 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8553 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8555 GL_INVALID_OPERATION,
8556 "glCopyTexSubImage2D", "async upload pending for texture");
8560 // Check we have compatible formats.
8561 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8562 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8563 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8565 if (!channels_needed ||
8566 (channels_needed & channels_exist) != channels_needed) {
8568 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8572 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8574 GL_INVALID_OPERATION,
8575 "glCopySubImage2D", "can not be used with depth or stencil textures");
8579 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8583 ScopedResolvedFrameBufferBinder binder(this, false, true);
8584 gfx::Size size = GetBoundReadFrameBufferSize();
8587 GLint copyWidth = 0;
8588 GLint copyHeight = 0;
8589 Clip(x, width, size.width(), ©X, ©Width);
8590 Clip(y, height, size.height(), ©Y, ©Height);
8592 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8594 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8600 copyWidth != width ||
8601 copyHeight != height) {
8602 // some part was clipped so clear the sub rect.
8603 uint32 pixels_size = 0;
8604 if (!GLES2Util::ComputeImageDataSizes(
8605 width, height, format, type, state_.unpack_alignment, &pixels_size,
8608 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8611 scoped_ptr<char[]> zero(new char[pixels_size]);
8612 memset(zero.get(), 0, pixels_size);
8613 ScopedModifyPixels modify(texture_ref);
8615 target, level, xoffset, yoffset, width, height,
8616 format, type, zero.get());
8619 if (copyHeight > 0 && copyWidth > 0) {
8620 GLint dx = copyX - x;
8621 GLint dy = copyY - y;
8622 GLint destX = xoffset + dx;
8623 GLint destY = yoffset + dy;
8624 ScopedModifyPixels modify(texture_ref);
8625 glCopyTexSubImage2D(target, level,
8626 destX, destY, copyX, copyY,
8627 copyWidth, copyHeight);
8631 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8632 error::Error* error,
8633 const char* function_name,
8642 const void * data) {
8643 (*error) = error::kNoError;
8644 if (!validators_->texture_target.IsValid(target)) {
8645 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8649 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8653 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8656 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8660 GL_INVALID_OPERATION,
8661 function_name, "unknown texture for target");
8664 Texture* texture = texture_ref->texture();
8665 GLenum current_type = 0;
8666 GLenum internal_format = 0;
8667 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
8669 GL_INVALID_OPERATION, function_name, "level does not exist.");
8672 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8673 function_name, format, type, internal_format, level)) {
8676 if (type != current_type) {
8678 GL_INVALID_OPERATION,
8679 function_name, "type does not match type of texture.");
8682 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8684 GL_INVALID_OPERATION,
8685 function_name, "async upload pending for texture");
8688 if (!texture->ValidForTexture(
8689 target, level, xoffset, yoffset, width, height, type)) {
8690 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8693 if ((GLES2Util::GetChannelsForFormat(format) &
8694 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8696 GL_INVALID_OPERATION,
8697 function_name, "can not supply data for depth or stencil textures");
8701 (*error) = error::kOutOfBounds;
8707 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8716 const void * data) {
8717 error::Error error = error::kNoError;
8718 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8719 xoffset, yoffset, width, height, format, type, data)) {
8722 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8724 Texture* texture = texture_ref->texture();
8725 GLsizei tex_width = 0;
8726 GLsizei tex_height = 0;
8727 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8729 if (xoffset != 0 || yoffset != 0 ||
8730 width != tex_width || height != tex_height) {
8731 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8734 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8735 return error::kNoError;
8737 ScopedTextureUploadTimer timer(&texture_state_);
8739 target, level, xoffset, yoffset, width, height, format, type, data);
8740 return error::kNoError;
8743 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8744 !texture->IsImmutable()) {
8745 ScopedTextureUploadTimer timer(&texture_state_);
8746 GLenum internal_format;
8748 texture->GetLevelType(target, level, &tex_type, &internal_format);
8749 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8752 target, level, internal_format, width, height, 0, format, type, data);
8754 ScopedTextureUploadTimer timer(&texture_state_);
8756 target, level, xoffset, yoffset, width, height, format, type, data);
8758 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8759 return error::kNoError;
8762 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8763 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8764 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8765 GLboolean internal = static_cast<GLboolean>(c.internal);
8766 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8767 return error::kNoError;
8769 GLenum target = static_cast<GLenum>(c.target);
8770 GLint level = static_cast<GLint>(c.level);
8771 GLint xoffset = static_cast<GLint>(c.xoffset);
8772 GLint yoffset = static_cast<GLint>(c.yoffset);
8773 GLsizei width = static_cast<GLsizei>(c.width);
8774 GLsizei height = static_cast<GLsizei>(c.height);
8775 GLenum format = static_cast<GLenum>(c.format);
8776 GLenum type = static_cast<GLenum>(c.type);
8778 if (!GLES2Util::ComputeImageDataSizes(
8779 width, height, format, type, state_.unpack_alignment, &data_size,
8781 return error::kOutOfBounds;
8783 const void* pixels = GetSharedMemoryAs<const void*>(
8784 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8785 return DoTexSubImage2D(
8786 target, level, xoffset, yoffset, width, height, format, type, pixels);
8789 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8790 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8791 GLuint index = static_cast<GLuint>(c.index);
8792 GLenum pname = static_cast<GLenum>(c.pname);
8793 typedef cmds::GetVertexAttribPointerv::Result Result;
8794 Result* result = GetSharedMemoryAs<Result*>(
8795 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8797 return error::kOutOfBounds;
8799 // Check that the client initialized the result.
8800 if (result->size != 0) {
8801 return error::kInvalidArguments;
8803 if (!validators_->vertex_pointer.IsValid(pname)) {
8804 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8805 "glGetVertexAttribPointerv", pname, "pname");
8806 return error::kNoError;
8808 if (index >= group_->max_vertex_attribs()) {
8810 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8811 return error::kNoError;
8813 result->SetNumResults(1);
8814 *result->GetData() =
8815 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8816 return error::kNoError;
8819 bool GLES2DecoderImpl::GetUniformSetup(
8820 GLuint program_id, GLint fake_location,
8821 uint32 shm_id, uint32 shm_offset,
8822 error::Error* error, GLint* real_location,
8823 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8826 DCHECK(result_pointer);
8827 DCHECK(result_type);
8828 DCHECK(real_location);
8829 *error = error::kNoError;
8830 // Make sure we have enough room for the result on failure.
8831 SizedResult<GLint>* result;
8832 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8833 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8835 *error = error::kOutOfBounds;
8838 *result_pointer = result;
8839 // Set the result size to 0 so the client does not have to check for success.
8840 result->SetNumResults(0);
8841 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8845 if (!program->IsValid()) {
8846 // Program was not linked successfully. (ie, glLinkProgram)
8848 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8851 *service_id = program->service_id();
8852 GLint array_index = -1;
8853 const Program::UniformInfo* uniform_info =
8854 program->GetUniformInfoByFakeLocation(
8855 fake_location, real_location, &array_index);
8856 if (!uniform_info) {
8857 // No such location.
8859 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8862 GLenum type = uniform_info->type;
8863 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8865 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8868 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8869 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8871 *error = error::kOutOfBounds;
8874 result->size = size;
8875 *result_type = type;
8879 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8880 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8881 GLuint program = c.program;
8882 GLint fake_location = c.location;
8885 GLint real_location = -1;
8888 if (GetUniformSetup(
8889 program, fake_location, c.params_shm_id, c.params_shm_offset,
8890 &error, &real_location, &service_id, &result, &result_type)) {
8892 service_id, real_location,
8893 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8898 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8899 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8900 GLuint program = c.program;
8901 GLint fake_location = c.location;
8903 GLint real_location = -1;
8905 typedef cmds::GetUniformfv::Result Result;
8908 if (GetUniformSetup(
8909 program, fake_location, c.params_shm_id, c.params_shm_offset,
8910 &error, &real_location, &service_id,
8911 reinterpret_cast<void**>(&result), &result_type)) {
8912 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8913 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8914 GLsizei num_values = result->GetNumResults();
8915 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8916 glGetUniformiv(service_id, real_location, temp.get());
8917 GLfloat* dst = result->GetData();
8918 for (GLsizei ii = 0; ii < num_values; ++ii) {
8919 dst[ii] = (temp[ii] != 0);
8922 glGetUniformfv(service_id, real_location, result->GetData());
8928 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8929 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8930 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8931 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8932 typedef cmds::GetShaderPrecisionFormat::Result Result;
8933 Result* result = GetSharedMemoryAs<Result*>(
8934 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8936 return error::kOutOfBounds;
8938 // Check that the client initialized the result.
8939 if (result->success != 0) {
8940 return error::kInvalidArguments;
8942 if (!validators_->shader_type.IsValid(shader_type)) {
8943 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8944 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8945 return error::kNoError;
8947 if (!validators_->shader_precision.IsValid(precision_type)) {
8948 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8949 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8950 return error::kNoError;
8953 result->success = 1; // true
8955 GLint range[2] = { 0, 0 };
8956 GLint precision = 0;
8957 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8959 result->min_range = range[0];
8960 result->max_range = range[1];
8961 result->precision = precision;
8963 return error::kNoError;
8966 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8967 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8968 uint32 result_size = c.result_size;
8969 GLuint program_id = static_cast<GLuint>(c.program);
8970 Program* program = GetProgramInfoNotShader(
8971 program_id, "glGetAttachedShaders");
8973 return error::kNoError;
8975 typedef cmds::GetAttachedShaders::Result Result;
8976 uint32 max_count = Result::ComputeMaxResults(result_size);
8977 Result* result = GetSharedMemoryAs<Result*>(
8978 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8980 return error::kOutOfBounds;
8982 // Check that the client initialized the result.
8983 if (result->size != 0) {
8984 return error::kInvalidArguments;
8987 glGetAttachedShaders(
8988 program->service_id(), max_count, &count, result->GetData());
8989 for (GLsizei ii = 0; ii < count; ++ii) {
8990 if (!shader_manager()->GetClientId(result->GetData()[ii],
8991 &result->GetData()[ii])) {
8993 return error::kGenericError;
8996 result->SetNumResults(count);
8997 return error::kNoError;
9000 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
9001 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
9002 GLuint program_id = c.program;
9003 GLuint index = c.index;
9004 uint32 name_bucket_id = c.name_bucket_id;
9005 typedef cmds::GetActiveUniform::Result Result;
9006 Result* result = GetSharedMemoryAs<Result*>(
9007 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9009 return error::kOutOfBounds;
9011 // Check that the client initialized the result.
9012 if (result->success != 0) {
9013 return error::kInvalidArguments;
9015 Program* program = GetProgramInfoNotShader(
9016 program_id, "glGetActiveUniform");
9018 return error::kNoError;
9020 const Program::UniformInfo* uniform_info =
9021 program->GetUniformInfo(index);
9022 if (!uniform_info) {
9024 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
9025 return error::kNoError;
9027 result->success = 1; // true.
9028 result->size = uniform_info->size;
9029 result->type = uniform_info->type;
9030 Bucket* bucket = CreateBucket(name_bucket_id);
9031 bucket->SetFromString(uniform_info->name.c_str());
9032 return error::kNoError;
9035 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
9036 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
9037 GLuint program_id = c.program;
9038 GLuint index = c.index;
9039 uint32 name_bucket_id = c.name_bucket_id;
9040 typedef cmds::GetActiveAttrib::Result Result;
9041 Result* result = GetSharedMemoryAs<Result*>(
9042 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9044 return error::kOutOfBounds;
9046 // Check that the client initialized the result.
9047 if (result->success != 0) {
9048 return error::kInvalidArguments;
9050 Program* program = GetProgramInfoNotShader(
9051 program_id, "glGetActiveAttrib");
9053 return error::kNoError;
9055 const Program::VertexAttrib* attrib_info =
9056 program->GetAttribInfo(index);
9059 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9060 return error::kNoError;
9062 result->success = 1; // true.
9063 result->size = attrib_info->size;
9064 result->type = attrib_info->type;
9065 Bucket* bucket = CreateBucket(name_bucket_id);
9066 bucket->SetFromString(attrib_info->name.c_str());
9067 return error::kNoError;
9070 error::Error GLES2DecoderImpl::HandleShaderBinary(
9071 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
9072 #if 1 // No binary shader support.
9073 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9074 return error::kNoError;
9076 GLsizei n = static_cast<GLsizei>(c.n);
9078 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9079 return error::kNoError;
9081 GLsizei length = static_cast<GLsizei>(c.length);
9083 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9084 return error::kNoError;
9087 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9088 return error::kOutOfBounds;
9090 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9091 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9092 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9093 const void* binary = GetSharedMemoryAs<const void*>(
9094 c.binary_shm_id, c.binary_shm_offset, length);
9095 if (shaders == NULL || binary == NULL) {
9096 return error::kOutOfBounds;
9098 scoped_array<GLuint> service_ids(new GLuint[n]);
9099 for (GLsizei ii = 0; ii < n; ++ii) {
9100 Shader* shader = GetShader(shaders[ii]);
9102 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9103 return error::kNoError;
9105 service_ids[ii] = shader->service_id();
9107 // TODO(gman): call glShaderBinary
9108 return error::kNoError;
9112 void GLES2DecoderImpl::DoSwapBuffers() {
9113 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9115 int this_frame_number = frame_number_++;
9116 // TRACE_EVENT for gpu tests:
9117 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9118 TRACE_EVENT_SCOPE_THREAD,
9119 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9120 "width", (is_offscreen ? offscreen_size_.width() :
9121 surface_->GetSize().width()));
9122 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9123 "offscreen", is_offscreen,
9124 "frame", this_frame_number);
9126 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9130 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9133 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9134 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9135 is_offscreen ? offscreen_size_ : surface_->GetSize());
9138 // If offscreen then don't actually SwapBuffers to the display. Just copy
9139 // the rendered frame to another frame buffer.
9141 TRACE_EVENT2("gpu", "Offscreen",
9142 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9143 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9144 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9145 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9147 if (workarounds().needs_offscreen_buffer_workaround) {
9148 offscreen_saved_frame_buffer_->Create();
9152 // Allocate the offscreen saved color texture.
9153 DCHECK(offscreen_saved_color_format_);
9154 offscreen_saved_color_texture_->AllocateStorage(
9155 offscreen_size_, offscreen_saved_color_format_, false);
9157 offscreen_saved_frame_buffer_->AttachRenderTexture(
9158 offscreen_saved_color_texture_.get());
9159 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9160 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9161 GL_FRAMEBUFFER_COMPLETE) {
9162 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9163 << "because offscreen saved FBO was incomplete.";
9164 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9168 // Clear the offscreen color texture.
9169 // TODO(piman): Is this still necessary?
9171 ScopedFrameBufferBinder binder(this,
9172 offscreen_saved_frame_buffer_->id());
9173 glClearColor(0, 0, 0, 0);
9174 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9175 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9176 glClear(GL_COLOR_BUFFER_BIT);
9177 RestoreClearState();
9181 UpdateParentTextureInfo();
9184 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9186 ScopedGLErrorSuppressor suppressor(
9187 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9189 if (IsOffscreenBufferMultisampled()) {
9190 // For multisampled buffers, resolve the frame buffer.
9191 ScopedResolvedFrameBufferBinder binder(this, true, false);
9193 ScopedFrameBufferBinder binder(this,
9194 offscreen_target_frame_buffer_->id());
9196 if (offscreen_target_buffer_preserved_) {
9197 // Copy the target frame buffer to the saved offscreen texture.
9198 offscreen_saved_color_texture_->Copy(
9199 offscreen_saved_color_texture_->size(),
9200 offscreen_saved_color_format_);
9202 // Flip the textures in the parent context via the texture manager.
9203 if (!!offscreen_saved_color_texture_info_.get())
9204 offscreen_saved_color_texture_info_->texture()->
9205 SetServiceId(offscreen_target_color_texture_->id());
9207 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9208 offscreen_target_frame_buffer_->AttachRenderTexture(
9209 offscreen_target_color_texture_.get());
9212 // Ensure the side effects of the copy are visible to the parent
9213 // context. There is no need to do this for ANGLE because it uses a
9214 // single D3D device for all contexts.
9215 if (!feature_info_->feature_flags().is_angle)
9219 if (!surface_->SwapBuffers()) {
9220 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9221 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9226 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9227 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
9228 Bucket* bucket = GetBucket(c.bucket_id);
9229 if (!bucket || bucket->size() == 0) {
9230 return error::kInvalidArguments;
9232 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9233 Result* result = GetSharedMemoryAs<Result*>(
9234 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9236 return error::kOutOfBounds;
9238 // Check that the client initialized the result.
9240 return error::kInvalidArguments;
9242 std::string feature_str;
9243 if (!bucket->GetAsString(&feature_str)) {
9244 return error::kInvalidArguments;
9247 // TODO(gman): make this some kind of table to function pointer thingy.
9248 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9249 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9250 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9251 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9252 // TODO(gman): decide how to remove the need for this const_cast.
9253 // I could make validators_ non const but that seems bad as this is the only
9254 // place it is needed. I could make some special friend class of validators
9255 // just to allow this to set them. That seems silly. I could refactor this
9256 // code to use the extension mechanism or the initialization attributes to
9257 // turn this feature on. Given that the only real point of this is to make
9258 // the conformance tests pass and given that there is lots of real work that
9259 // needs to be done it seems like refactoring for one to one of those
9260 // methods is a very low priority.
9261 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9262 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9263 force_webgl_glsl_validation_ = true;
9264 InitializeShaderTranslator();
9266 return error::kNoError;
9269 *result = 1; // true.
9270 return error::kNoError;
9273 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9274 uint32 immediate_data_size,
9275 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9276 Bucket* bucket = CreateBucket(c.bucket_id);
9277 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9278 info->Initialize(disallowed_features_);
9279 bucket->SetFromString(info->extensions().c_str());
9280 return error::kNoError;
9283 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9284 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9285 Bucket* bucket = GetBucket(c.bucket_id);
9286 if (!bucket || bucket->size() == 0) {
9287 return error::kInvalidArguments;
9289 std::string feature_str;
9290 if (!bucket->GetAsString(&feature_str)) {
9291 return error::kInvalidArguments;
9294 bool desire_webgl_glsl_validation =
9295 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9296 bool desire_standard_derivatives = false;
9297 bool desire_frag_depth = false;
9298 bool desire_draw_buffers = false;
9299 bool desire_shader_texture_lod = false;
9300 if (force_webgl_glsl_validation_) {
9301 desire_standard_derivatives =
9302 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9304 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9305 desire_draw_buffers =
9306 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9307 desire_shader_texture_lod =
9308 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9311 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9312 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9313 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9314 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9315 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9316 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9317 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9318 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9319 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
9320 InitializeShaderTranslator();
9323 UpdateCapabilities();
9325 return error::kNoError;
9328 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9329 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9330 GLuint count = c.count;
9332 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9333 return error::kOutOfBounds;
9335 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9336 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9337 if (pnames == NULL) {
9338 return error::kOutOfBounds;
9341 // We have to copy them since we use them twice so the client
9342 // can't change them between the time we validate them and the time we use
9344 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9345 memcpy(enums.get(), pnames, pnames_size);
9347 // Count up the space needed for the result.
9348 uint32 num_results = 0;
9349 for (GLuint ii = 0; ii < count; ++ii) {
9350 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9352 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9353 "glGetMultipleCHROMIUM", enums[ii], "pname");
9354 return error::kNoError;
9356 // Num will never be more than 4.
9358 if (!SafeAddUint32(num_results, num, &num_results)) {
9359 return error::kOutOfBounds;
9363 uint32 result_size = 0;
9364 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9365 return error::kOutOfBounds;
9368 if (result_size != static_cast<uint32>(c.size)) {
9371 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9372 return error::kNoError;
9375 GLint* results = GetSharedMemoryAs<GLint*>(
9376 c.results_shm_id, c.results_shm_offset, result_size);
9377 if (results == NULL) {
9378 return error::kOutOfBounds;
9381 // Check the results have been cleared in case the context was lost.
9382 for (uint32 ii = 0; ii < num_results; ++ii) {
9384 return error::kInvalidArguments;
9389 GLint* start = results;
9390 for (GLuint ii = 0; ii < count; ++ii) {
9391 GLsizei num_written = 0;
9392 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9393 !GetHelper(enums[ii], results, &num_written)) {
9394 DoGetIntegerv(enums[ii], results);
9396 results += num_written;
9399 // Just to verify. Should this be a DCHECK?
9400 if (static_cast<uint32>(results - start) != num_results) {
9401 return error::kOutOfBounds;
9404 return error::kNoError;
9407 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9408 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9409 GLuint program_id = static_cast<GLuint>(c.program);
9410 uint32 bucket_id = c.bucket_id;
9411 Bucket* bucket = CreateBucket(bucket_id);
9412 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9413 Program* program = NULL;
9414 program = GetProgram(program_id);
9415 if (!program || !program->IsValid()) {
9416 return error::kNoError;
9418 program->GetProgramInfo(program_manager(), bucket);
9419 return error::kNoError;
9422 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9423 switch (reset_status_) {
9425 // TODO(kbr): improve the precision of the error code in this case.
9426 // Consider delegating to context for error code if MakeCurrent fails.
9427 return error::kUnknown;
9428 case GL_GUILTY_CONTEXT_RESET_ARB:
9429 return error::kGuilty;
9430 case GL_INNOCENT_CONTEXT_RESET_ARB:
9431 return error::kInnocent;
9432 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9433 return error::kUnknown;
9437 return error::kUnknown;
9440 bool GLES2DecoderImpl::WasContextLost() {
9441 if (reset_status_ != GL_NO_ERROR) {
9444 if (context_->WasAllocatedUsingRobustnessExtension()) {
9445 GLenum status = GL_NO_ERROR;
9446 if (has_robustness_extension_)
9447 status = glGetGraphicsResetStatusARB();
9448 if (status != GL_NO_ERROR) {
9449 // The graphics card was reset. Signal a lost context to the application.
9450 reset_status_ = status;
9451 reset_by_robustness_extension_ = true;
9452 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9453 << " context lost via ARB/EXT_robustness. Reset status = "
9454 << GLES2Util::GetStringEnum(status);
9461 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9462 return WasContextLost() && reset_by_robustness_extension_;
9465 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9466 // Only loses the context once.
9467 if (reset_status_ != GL_NO_ERROR) {
9471 // Marks this context as lost.
9472 reset_status_ = reset_status;
9473 current_decoder_error_ = error::kLostContext;
9476 error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9477 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
9478 GLenum current = static_cast<GLenum>(c.current);
9479 GLenum other = static_cast<GLenum>(c.other);
9480 if (!validators_->reset_status.IsValid(current)) {
9481 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9482 "glLoseContextCHROMIUM", current, "current");
9484 if (!validators_->reset_status.IsValid(other)) {
9485 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
9487 group_->LoseContexts(other);
9488 reset_status_ = current;
9489 current_decoder_error_ = error::kLostContext;
9490 return error::kLostContext;
9493 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9494 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9495 return error::kUnknownCommand;
9498 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9499 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9500 group_->mailbox_manager()->PullTextureUpdates();
9501 if (wait_sync_point_callback_.is_null())
9502 return error::kNoError;
9504 return wait_sync_point_callback_.Run(c.sync_point) ?
9505 error::kNoError : error::kDeferCommandUntilLater;
9508 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9509 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9510 if (surface_->DeferDraws())
9511 return error::kDeferCommandUntilLater;
9512 if (!surface_->SetBackbufferAllocation(false))
9513 return error::kLostContext;
9514 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9515 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9516 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9517 return error::kNoError;
9520 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9521 GLsizei n, const GLuint* client_ids) {
9522 for (GLsizei ii = 0; ii < n; ++ii) {
9523 if (query_manager_->GetQuery(client_ids[ii])) {
9527 query_manager_->GenQueries(n, client_ids);
9531 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9532 GLsizei n, const GLuint* client_ids) {
9533 for (GLsizei ii = 0; ii < n; ++ii) {
9534 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9535 if (query && !query->IsDeleted()) {
9536 ContextState::QueryMap::iterator it =
9537 state_.current_queries.find(query->target());
9538 if (it != state_.current_queries.end())
9539 state_.current_queries.erase(it);
9541 query->Destroy(true);
9543 query_manager_->RemoveQuery(client_ids[ii]);
9547 bool GLES2DecoderImpl::ProcessPendingQueries() {
9548 if (query_manager_.get() == NULL) {
9551 if (!query_manager_->ProcessPendingQueries()) {
9552 current_decoder_error_ = error::kOutOfBounds;
9554 return query_manager_->HavePendingQueries();
9557 // Note that if there are no pending readpixels right now,
9558 // this function will call the callback immediately.
9559 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9560 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9561 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9567 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9568 while (!pending_readpixel_fences_.empty() &&
9569 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9570 std::vector<base::Closure> callbacks =
9571 pending_readpixel_fences_.front()->callbacks;
9572 pending_readpixel_fences_.pop();
9573 for (size_t i = 0; i < callbacks.size(); i++) {
9579 bool GLES2DecoderImpl::HasMoreIdleWork() {
9580 return !pending_readpixel_fences_.empty() ||
9581 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9584 void GLES2DecoderImpl::PerformIdleWork() {
9585 ProcessPendingReadPixels();
9586 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9588 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9589 ProcessFinishedAsyncTransfers();
9592 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9593 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9594 GLenum target = static_cast<GLenum>(c.target);
9595 GLuint client_id = static_cast<GLuint>(c.id);
9596 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9597 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9600 case GL_COMMANDS_ISSUED_CHROMIUM:
9601 case GL_LATENCY_QUERY_CHROMIUM:
9602 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9603 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9604 case GL_GET_ERROR_QUERY_CHROMIUM:
9606 case GL_COMMANDS_COMPLETED_CHROMIUM:
9607 if (!features().chromium_sync_query) {
9609 GL_INVALID_OPERATION, "glBeginQueryEXT",
9610 "not enabled for commands completed queries");
9611 return error::kNoError;
9615 if (!features().occlusion_query_boolean) {
9617 GL_INVALID_OPERATION, "glBeginQueryEXT",
9618 "not enabled for occlusion queries");
9619 return error::kNoError;
9624 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9626 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9627 return error::kNoError;
9630 if (client_id == 0) {
9631 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9632 return error::kNoError;
9635 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9637 if (!query_manager_->IsValidQuery(client_id)) {
9638 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9640 "id not made by glGenQueriesEXT");
9641 return error::kNoError;
9643 query = query_manager_->CreateQuery(
9644 target, client_id, sync_shm_id, sync_shm_offset);
9647 if (query->target() != target) {
9649 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9650 return error::kNoError;
9651 } else if (query->shm_id() != sync_shm_id ||
9652 query->shm_offset() != sync_shm_offset) {
9653 DLOG(ERROR) << "Shared memory used by query not the same as before";
9654 return error::kInvalidArguments;
9657 if (!query_manager_->BeginQuery(query)) {
9658 return error::kOutOfBounds;
9661 state_.current_queries[target] = query;
9662 return error::kNoError;
9665 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9666 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9667 GLenum target = static_cast<GLenum>(c.target);
9668 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9669 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9671 if (it == state_.current_queries.end()) {
9673 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9674 return error::kNoError;
9677 QueryManager::Query* query = it->second.get();
9678 if (!query_manager_->EndQuery(query, submit_count)) {
9679 return error::kOutOfBounds;
9682 query_manager_->ProcessPendingTransferQueries();
9684 state_.current_queries.erase(it);
9685 return error::kNoError;
9688 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9689 GLsizei n, const GLuint* client_ids) {
9690 for (GLsizei ii = 0; ii < n; ++ii) {
9691 if (GetVertexAttribManager(client_ids[ii])) {
9696 if (!features().native_vertex_array_object) {
9698 for (GLsizei ii = 0; ii < n; ++ii) {
9699 CreateVertexAttribManager(client_ids[ii], 0, true);
9702 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9704 glGenVertexArraysOES(n, service_ids.get());
9705 for (GLsizei ii = 0; ii < n; ++ii) {
9706 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
9713 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9714 GLsizei n, const GLuint* client_ids) {
9715 for (GLsizei ii = 0; ii < n; ++ii) {
9716 VertexAttribManager* vao =
9717 GetVertexAttribManager(client_ids[ii]);
9718 if (vao && !vao->IsDeleted()) {
9719 if (state_.vertex_attrib_manager.get() == vao) {
9720 DoBindVertexArrayOES(0);
9722 RemoveVertexAttribManager(client_ids[ii]);
9727 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9728 VertexAttribManager* vao = NULL;
9729 if (client_id != 0) {
9730 vao = GetVertexAttribManager(client_id);
9732 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9733 // only allows names that have been previously generated. As such, we do
9734 // not generate new names here.
9736 GL_INVALID_OPERATION,
9737 "glBindVertexArrayOES", "bad vertex array id.");
9738 current_decoder_error_ = error::kNoError;
9742 vao = state_.default_vertex_attrib_manager.get();
9745 // Only set the VAO state if it's changed
9746 if (state_.vertex_attrib_manager.get() != vao) {
9747 state_.vertex_attrib_manager = vao;
9748 if (!features().native_vertex_array_object) {
9749 EmulateVertexArrayState();
9751 GLuint service_id = vao->service_id();
9752 glBindVertexArrayOES(service_id);
9757 // Used when OES_vertex_array_object isn't natively supported
9758 void GLES2DecoderImpl::EmulateVertexArrayState() {
9759 // Setup the Vertex attribute state
9760 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9761 RestoreStateForAttrib(vv);
9764 // Setup the element buffer
9765 Buffer* element_array_buffer =
9766 state_.vertex_attrib_manager->element_array_buffer();
9767 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9768 element_array_buffer ? element_array_buffer->service_id() : 0);
9771 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9772 const VertexAttribManager* vao =
9773 GetVertexAttribManager(client_id);
9774 return vao && vao->IsValid() && !vao->IsDeleted();
9777 #if defined(OS_MACOSX)
9778 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9779 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9781 if (it != texture_to_io_surface_map_.end()) {
9782 // Found a previous IOSurface bound to this texture; release it.
9783 CFTypeRef surface = it->second;
9785 texture_to_io_surface_map_.erase(it);
9790 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9791 GLenum target, GLsizei width, GLsizei height,
9792 GLuint io_surface_id, GLuint plane) {
9793 #if defined(OS_MACOSX)
9794 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9796 GL_INVALID_OPERATION,
9797 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9801 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9802 if (!surface_support) {
9804 GL_INVALID_OPERATION,
9805 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
9809 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9810 // This might be supported in the future, and if we could require
9811 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9812 // could delete a lot of code. For now, perform strict validation so we
9813 // know what's going on.
9815 GL_INVALID_OPERATION,
9816 "glTexImageIOSurface2DCHROMIUM",
9817 "requires TEXTURE_RECTANGLE_ARB target");
9821 // Default target might be conceptually valid, but disallow it to avoid
9823 TextureRef* texture_ref =
9824 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9827 GL_INVALID_OPERATION,
9828 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9832 // Look up the new IOSurface. Note that because of asynchrony
9833 // between processes this might fail; during live resizing the
9834 // plugin process might allocate and release an IOSurface before
9835 // this process gets a chance to look it up. Hold on to any old
9836 // IOSurface in this case.
9837 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9840 GL_INVALID_OPERATION,
9841 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9845 // Release any IOSurface previously bound to this texture.
9846 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9848 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9849 texture_to_io_surface_map_.insert(
9850 std::make_pair(texture_ref->service_id(), surface));
9852 CGLContextObj context =
9853 static_cast<CGLContextObj>(context_->GetHandle());
9855 CGLError err = surface_support->CGLTexImageIOSurface2D(
9862 GL_UNSIGNED_INT_8_8_8_8_REV,
9866 if (err != kCGLNoError) {
9868 GL_INVALID_OPERATION,
9869 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9873 texture_manager()->SetLevelInfo(
9874 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9875 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9878 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9879 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9883 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9884 switch (internalformat) {
9895 case GL_LUMINANCE8_ALPHA8_EXT:
9896 return GL_LUMINANCE_ALPHA;
9897 case GL_LUMINANCE8_EXT:
9898 return GL_LUMINANCE;
9901 case GL_RGBA32F_EXT:
9905 case GL_ALPHA32F_EXT:
9907 case GL_LUMINANCE32F_EXT:
9908 return GL_LUMINANCE;
9909 case GL_LUMINANCE_ALPHA32F_EXT:
9910 return GL_LUMINANCE_ALPHA;
9911 case GL_RGBA16F_EXT:
9915 case GL_ALPHA16F_EXT:
9917 case GL_LUMINANCE16F_EXT:
9918 return GL_LUMINANCE;
9919 case GL_LUMINANCE_ALPHA16F_EXT:
9920 return GL_LUMINANCE_ALPHA;
9928 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9929 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9930 GLenum internal_format, GLenum dest_type) {
9931 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
9933 TextureRef* dest_texture_ref = GetTexture(dest_id);
9934 TextureRef* source_texture_ref = GetTexture(source_id);
9936 if (!source_texture_ref || !dest_texture_ref) {
9938 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9942 if (GL_TEXTURE_2D != target) {
9944 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9948 Texture* source_texture = source_texture_ref->texture();
9949 Texture* dest_texture = dest_texture_ref->texture();
9950 if (dest_texture->target() != GL_TEXTURE_2D ||
9951 (source_texture->target() != GL_TEXTURE_2D &&
9952 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
9953 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9954 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9955 "glCopyTextureCHROMIUM",
9956 "invalid texture target binding");
9960 int source_width, source_height, dest_width, dest_height;
9962 gfx::GLImage* image =
9963 source_texture->GetLevelImage(source_texture->target(), 0);
9965 gfx::Size size = image->GetSize();
9966 source_width = size.width();
9967 source_height = size.height();
9968 if (source_width <= 0 || source_height <= 0) {
9971 "glCopyTextureChromium", "invalid image size");
9975 if (!source_texture->GetLevelSize(
9976 source_texture->target(), 0, &source_width, &source_height)) {
9977 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9978 "glCopyTextureChromium",
9979 "source texture has no level 0");
9983 // Check that this type of texture is allowed.
9984 if (!texture_manager()->ValidForTarget(
9985 source_texture->target(), level, source_width, source_height, 1)) {
9987 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9992 // Clear the source texture if necessary.
9993 if (!texture_manager()->ClearTextureLevel(
9994 this, source_texture_ref, source_texture->target(), 0)) {
9996 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
10000 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10001 // needed because it takes 10s of milliseconds to initialize.
10002 if (!copy_texture_CHROMIUM_.get()) {
10003 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10004 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
10005 copy_texture_CHROMIUM_->Initialize(this);
10006 RestoreCurrentFramebufferBindings();
10007 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
10011 GLenum dest_type_previous;
10012 GLenum dest_internal_format;
10013 bool dest_level_defined = dest_texture->GetLevelSize(
10014 GL_TEXTURE_2D, level, &dest_width, &dest_height);
10016 if (dest_level_defined) {
10017 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
10018 &dest_internal_format);
10021 // Resize the destination texture to the dimensions of the source texture.
10022 if (!dest_level_defined || dest_width != source_width ||
10023 dest_height != source_height ||
10024 dest_internal_format != internal_format ||
10025 dest_type_previous != dest_type) {
10026 // Ensure that the glTexImage2D succeeds.
10027 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10028 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10030 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
10031 0, internal_format, dest_type, NULL);
10032 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10033 if (error != GL_NO_ERROR) {
10034 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
10038 texture_manager()->SetLevelInfo(
10039 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
10040 source_height, 1, 0, internal_format, dest_type, true);
10042 texture_manager()->SetLevelCleared(
10043 dest_texture_ref, GL_TEXTURE_2D, level, true);
10046 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
10047 ScopedModifyPixels modify(dest_texture_ref);
10049 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10050 // before presenting.
10051 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
10052 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10053 // instead of using default matrix crbug.com/226218.
10054 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
10055 0.0f, 1.0f, 0.0f, 0.0f,
10056 0.0f, 0.0f, 1.0f, 0.0f,
10057 0.0f, 0.0f, 0.0f, 1.0f};
10058 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
10060 source_texture->target(),
10061 dest_texture->target(),
10062 source_texture->service_id(),
10063 dest_texture->service_id(), level,
10064 source_width, source_height,
10066 unpack_premultiply_alpha_,
10067 unpack_unpremultiply_alpha_,
10070 copy_texture_CHROMIUM_->DoCopyTexture(
10072 source_texture->target(),
10073 dest_texture->target(),
10074 source_texture->service_id(),
10075 dest_texture->service_id(), level,
10076 source_width, source_height,
10078 unpack_premultiply_alpha_,
10079 unpack_unpremultiply_alpha_);
10082 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10085 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10086 switch (internalformat) {
10088 return GL_UNSIGNED_SHORT_5_6_5;
10090 return GL_UNSIGNED_SHORT_4_4_4_4;
10092 return GL_UNSIGNED_SHORT_5_5_5_1;
10094 return GL_UNSIGNED_BYTE;
10096 return GL_UNSIGNED_BYTE;
10097 case GL_LUMINANCE8_ALPHA8_EXT:
10098 return GL_UNSIGNED_BYTE;
10099 case GL_LUMINANCE8_EXT:
10100 return GL_UNSIGNED_BYTE;
10101 case GL_ALPHA8_EXT:
10102 return GL_UNSIGNED_BYTE;
10103 case GL_RGBA32F_EXT:
10105 case GL_RGB32F_EXT:
10107 case GL_ALPHA32F_EXT:
10109 case GL_LUMINANCE32F_EXT:
10111 case GL_LUMINANCE_ALPHA32F_EXT:
10113 case GL_RGBA16F_EXT:
10114 return GL_HALF_FLOAT_OES;
10115 case GL_RGB16F_EXT:
10116 return GL_HALF_FLOAT_OES;
10117 case GL_ALPHA16F_EXT:
10118 return GL_HALF_FLOAT_OES;
10119 case GL_LUMINANCE16F_EXT:
10120 return GL_HALF_FLOAT_OES;
10121 case GL_LUMINANCE_ALPHA16F_EXT:
10122 return GL_HALF_FLOAT_OES;
10124 return GL_UNSIGNED_BYTE;
10130 void GLES2DecoderImpl::DoTexStorage2DEXT(
10133 GLenum internal_format,
10136 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
10137 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10138 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10139 LOCAL_SET_GL_ERROR(
10140 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10143 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10145 if (!texture_ref) {
10146 LOCAL_SET_GL_ERROR(
10147 GL_INVALID_OPERATION,
10148 "glTexStorage2DEXT", "unknown texture for target");
10151 Texture* texture = texture_ref->texture();
10152 if (texture->IsAttachedToFramebuffer()) {
10153 framebuffer_state_.clear_state_dirty = true;
10155 if (texture->IsImmutable()) {
10156 LOCAL_SET_GL_ERROR(
10157 GL_INVALID_OPERATION,
10158 "glTexStorage2DEXT", "texture is immutable");
10162 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10163 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10166 GLsizei level_width = width;
10167 GLsizei level_height = height;
10168 uint32 estimated_size = 0;
10169 for (int ii = 0; ii < levels; ++ii) {
10170 uint32 level_size = 0;
10171 if (!GLES2Util::ComputeImageDataSizes(
10172 level_width, level_height, format, type, state_.unpack_alignment,
10173 &estimated_size, NULL, NULL) ||
10174 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10175 LOCAL_SET_GL_ERROR(
10176 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10179 level_width = std::max(1, level_width >> 1);
10180 level_height = std::max(1, level_height >> 1);
10182 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10183 LOCAL_SET_GL_ERROR(
10184 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10189 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10190 glTexStorage2DEXT(target, levels, internal_format, width, height);
10191 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10192 if (error == GL_NO_ERROR) {
10193 GLsizei level_width = width;
10194 GLsizei level_height = height;
10195 for (int ii = 0; ii < levels; ++ii) {
10196 texture_manager()->SetLevelInfo(
10197 texture_ref, target, ii, format,
10198 level_width, level_height, 1, 0, format, type, false);
10199 level_width = std::max(1, level_width >> 1);
10200 level_height = std::max(1, level_height >> 1);
10202 texture->SetImmutable(true);
10206 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10207 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
10208 return error::kUnknownCommand;
10211 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10212 const GLbyte* data) {
10213 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10214 "context", logger_.GetLogPrefix(),
10215 "mailbox[0]", static_cast<unsigned char>(data[0]));
10217 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10218 DLOG_IF(ERROR, !mailbox.Verify()) << "ProduceTextureCHROMIUM was passed a "
10219 "mailbox that was not generated by "
10220 "GenMailboxCHROMIUM.";
10222 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10224 if (!texture_ref) {
10225 LOCAL_SET_GL_ERROR(
10226 GL_INVALID_OPERATION,
10227 "glProduceTextureCHROMIUM", "unknown texture for target");
10231 Texture* produced = texture_manager()->Produce(texture_ref);
10233 LOCAL_SET_GL_ERROR(
10234 GL_INVALID_OPERATION,
10235 "glProduceTextureCHROMIUM", "invalid texture");
10239 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10242 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10243 const GLbyte* data) {
10244 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10245 "context", logger_.GetLogPrefix(),
10246 "mailbox[0]", static_cast<unsigned char>(data[0]));
10247 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10248 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10249 "mailbox that was not generated by "
10250 "GenMailboxCHROMIUM.";
10252 scoped_refptr<TextureRef> texture_ref =
10253 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10254 if (!texture_ref.get()) {
10255 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10256 "glConsumeTextureCHROMIUM",
10257 "unknown texture for target");
10260 GLuint client_id = texture_ref->client_id();
10262 LOCAL_SET_GL_ERROR(
10263 GL_INVALID_OPERATION,
10264 "glConsumeTextureCHROMIUM", "unknown texture for target");
10267 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10269 LOCAL_SET_GL_ERROR(
10270 GL_INVALID_OPERATION,
10271 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10274 if (texture->target() != target) {
10275 LOCAL_SET_GL_ERROR(
10276 GL_INVALID_OPERATION,
10277 "glConsumeTextureCHROMIUM", "invalid target");
10281 DeleteTexturesHelper(1, &client_id);
10282 texture_ref = texture_manager()->Consume(client_id, texture);
10283 glBindTexture(target, texture_ref->service_id());
10285 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10286 unit.bind_target = target;
10288 case GL_TEXTURE_2D:
10289 unit.bound_texture_2d = texture_ref;
10291 case GL_TEXTURE_CUBE_MAP:
10292 unit.bound_texture_cube_map = texture_ref;
10294 case GL_TEXTURE_EXTERNAL_OES:
10295 unit.bound_texture_external_oes = texture_ref;
10297 case GL_TEXTURE_RECTANGLE_ARB:
10298 unit.bound_texture_rectangle_arb = texture_ref;
10301 NOTREACHED(); // Validation should prevent us getting here.
10306 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10307 GLsizei length, const GLchar* marker) {
10311 debug_marker_manager_.SetMarker(
10312 length ? std::string(marker, length) : std::string(marker));
10315 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10316 GLsizei length, const GLchar* marker) {
10320 std::string name = length ? std::string(marker, length) : std::string(marker);
10321 debug_marker_manager_.PushGroup(name);
10322 gpu_tracer_->Begin(name, kTraceGroupMarker);
10325 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10326 debug_marker_manager_.PopGroup();
10327 gpu_tracer_->End(kTraceGroupMarker);
10330 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10331 GLenum target, GLint image_id) {
10332 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10334 if (target == GL_TEXTURE_CUBE_MAP) {
10335 LOCAL_SET_GL_ERROR(
10337 "glBindTexImage2DCHROMIUM", "invalid target");
10341 // Default target might be conceptually valid, but disallow it to avoid
10343 TextureRef* texture_ref =
10344 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10345 if (!texture_ref) {
10346 LOCAL_SET_GL_ERROR(
10347 GL_INVALID_OPERATION,
10348 "glBindTexImage2DCHROMIUM", "no texture bound");
10352 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10354 LOCAL_SET_GL_ERROR(
10355 GL_INVALID_OPERATION,
10356 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10361 ScopedGLErrorSuppressor suppressor(
10362 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10363 if (!gl_image->BindTexImage(target)) {
10364 LOCAL_SET_GL_ERROR(
10365 GL_INVALID_OPERATION,
10366 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10371 gfx::Size size = gl_image->GetSize();
10372 texture_manager()->SetLevelInfo(
10373 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10374 GL_RGBA, GL_UNSIGNED_BYTE, true);
10375 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10378 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10379 GLenum target, GLint image_id) {
10380 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10382 // Default target might be conceptually valid, but disallow it to avoid
10384 TextureRef* texture_ref =
10385 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10386 if (!texture_ref) {
10387 LOCAL_SET_GL_ERROR(
10388 GL_INVALID_OPERATION,
10389 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10393 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10395 LOCAL_SET_GL_ERROR(
10396 GL_INVALID_OPERATION,
10397 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10401 // Do nothing when image is not currently bound.
10402 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10406 ScopedGLErrorSuppressor suppressor(
10407 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10408 gl_image->ReleaseTexImage(target);
10411 texture_manager()->SetLevelInfo(
10412 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10413 GL_RGBA, GL_UNSIGNED_BYTE, false);
10416 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10417 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10418 Bucket* bucket = GetBucket(c.bucket_id);
10419 if (!bucket || bucket->size() == 0) {
10420 return error::kInvalidArguments;
10422 std::string command_name;
10423 if (!bucket->GetAsString(&command_name)) {
10424 return error::kInvalidArguments;
10426 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10427 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10428 LOCAL_SET_GL_ERROR(
10429 GL_INVALID_OPERATION,
10430 "glTraceBeginCHROMIUM", "unable to create begin trace");
10431 return error::kNoError;
10433 return error::kNoError;
10436 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10437 if (gpu_tracer_->CurrentName().empty()) {
10438 LOCAL_SET_GL_ERROR(
10439 GL_INVALID_OPERATION,
10440 "glTraceEndCHROMIUM", "no trace begin found");
10443 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10444 gpu_tracer_->End(kTraceCHROMIUM);
10447 void GLES2DecoderImpl::DoDrawBuffersEXT(
10448 GLsizei count, const GLenum* bufs) {
10449 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10450 LOCAL_SET_GL_ERROR(
10452 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10456 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10458 for (GLsizei i = 0; i < count; ++i) {
10459 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10460 bufs[i] != GL_NONE) {
10461 LOCAL_SET_GL_ERROR(
10462 GL_INVALID_OPERATION,
10463 "glDrawBuffersEXT",
10464 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10468 glDrawBuffersARB(count, bufs);
10469 framebuffer->SetDrawBuffers(count, bufs);
10470 } else { // backbuffer
10472 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10473 LOCAL_SET_GL_ERROR(
10474 GL_INVALID_OPERATION,
10475 "glDrawBuffersEXT",
10476 "more than one buffer or bufs not GL_NONE or GL_BACK");
10479 GLenum mapped_buf = bufs[0];
10480 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10481 bufs[0] == GL_BACK) {
10482 mapped_buf = GL_COLOR_ATTACHMENT0;
10484 glDrawBuffersARB(count, &mapped_buf);
10485 group_->set_draw_buffer(bufs[0]);
10489 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10490 const char* function_name,
10491 TextureRef* texture_ref,
10494 const void * data) {
10495 // We only support async uploads to 2D textures for now.
10496 if (GL_TEXTURE_2D != target) {
10497 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10500 // We only support uploads to level zero for now.
10502 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10505 // A transfer buffer must be bound, even for asyncTexImage2D.
10506 if (data == NULL) {
10507 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10510 // We only support one async transfer in progress.
10511 if (!texture_ref ||
10512 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10513 LOCAL_SET_GL_ERROR(
10514 GL_INVALID_OPERATION,
10515 function_name, "transfer already in progress");
10521 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10522 uint32 async_upload_token,
10523 uint32 sync_data_shm_id,
10524 uint32 sync_data_shm_offset) {
10525 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
10526 if (!buffer || !buffer->GetDataAddress(sync_data_shm_offset,
10527 sizeof(AsyncUploadSync)))
10528 return base::Closure();
10530 AsyncMemoryParams mem_params(buffer,
10531 sync_data_shm_offset,
10532 sizeof(AsyncUploadSync));
10534 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
10535 new AsyncUploadTokenCompletionObserver(async_upload_token));
10538 &AsyncPixelTransferManager::AsyncNotifyCompletion,
10539 base::Unretained(GetAsyncPixelTransferManager()),
10544 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10545 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10546 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10547 GLenum target = static_cast<GLenum>(c.target);
10548 GLint level = static_cast<GLint>(c.level);
10549 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10550 // unsigned integer for internalformat.
10551 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10552 GLsizei width = static_cast<GLsizei>(c.width);
10553 GLsizei height = static_cast<GLsizei>(c.height);
10554 GLint border = static_cast<GLint>(c.border);
10555 GLenum format = static_cast<GLenum>(c.format);
10556 GLenum type = static_cast<GLenum>(c.type);
10557 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10558 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10559 uint32 pixels_size;
10560 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10561 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10562 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10564 base::ScopedClosureRunner scoped_completion_callback;
10565 if (async_upload_token) {
10566 base::Closure completion_closure =
10567 AsyncUploadTokenCompletionClosure(async_upload_token,
10569 sync_data_shm_offset);
10570 if (completion_closure.is_null())
10571 return error::kInvalidArguments;
10573 scoped_completion_callback.Reset(completion_closure);
10576 // TODO(epenner): Move this and copies of this memory validation
10577 // into ValidateTexImage2D step.
10578 if (!GLES2Util::ComputeImageDataSizes(
10579 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10581 return error::kOutOfBounds;
10583 const void* pixels = NULL;
10584 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10585 pixels = GetSharedMemoryAs<const void*>(
10586 pixels_shm_id, pixels_shm_offset, pixels_size);
10588 return error::kOutOfBounds;
10592 TextureManager::DoTextImage2DArguments args = {
10593 target, level, internal_format, width, height, border, format, type,
10594 pixels, pixels_size};
10595 TextureRef* texture_ref;
10596 // All the normal glTexSubImage2D validation.
10597 if (!texture_manager()->ValidateTexImage2D(
10598 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10599 return error::kNoError;
10602 // Extra async validation.
10603 Texture* texture = texture_ref->texture();
10604 if (!ValidateAsyncTransfer(
10605 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10606 return error::kNoError;
10608 // Don't allow async redefinition of a textures.
10609 if (texture->IsDefined()) {
10610 LOCAL_SET_GL_ERROR(
10611 GL_INVALID_OPERATION,
10612 "glAsyncTexImage2DCHROMIUM", "already defined");
10613 return error::kNoError;
10616 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10617 LOCAL_SET_GL_ERROR(
10618 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10619 return error::kNoError;
10622 // Setup the parameters.
10623 AsyncTexImage2DParams tex_params = {
10624 target, level, static_cast<GLenum>(internal_format),
10625 width, height, border, format, type};
10626 AsyncMemoryParams mem_params(
10627 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
10629 // Set up the async state if needed, and make the texture
10630 // immutable so the async state stays valid. The level info
10631 // is set up lazily when the transfer completes.
10632 AsyncPixelTransferDelegate* delegate =
10633 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10635 texture->SetImmutable(true);
10637 delegate->AsyncTexImage2D(
10640 base::Bind(&TextureManager::SetLevelInfoFromParams,
10641 // The callback is only invoked if the transfer delegate still
10642 // exists, which implies through manager->texture_ref->state
10643 // ownership that both of these pointers are valid.
10644 base::Unretained(texture_manager()),
10645 base::Unretained(texture_ref),
10647 return error::kNoError;
10650 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10651 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10652 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10653 GLenum target = static_cast<GLenum>(c.target);
10654 GLint level = static_cast<GLint>(c.level);
10655 GLint xoffset = static_cast<GLint>(c.xoffset);
10656 GLint yoffset = static_cast<GLint>(c.yoffset);
10657 GLsizei width = static_cast<GLsizei>(c.width);
10658 GLsizei height = static_cast<GLsizei>(c.height);
10659 GLenum format = static_cast<GLenum>(c.format);
10660 GLenum type = static_cast<GLenum>(c.type);
10661 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10662 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10663 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10665 base::ScopedClosureRunner scoped_completion_callback;
10666 if (async_upload_token) {
10667 base::Closure completion_closure =
10668 AsyncUploadTokenCompletionClosure(async_upload_token,
10670 sync_data_shm_offset);
10671 if (completion_closure.is_null())
10672 return error::kInvalidArguments;
10674 scoped_completion_callback.Reset(completion_closure);
10677 // TODO(epenner): Move this and copies of this memory validation
10678 // into ValidateTexSubImage2D step.
10680 if (!GLES2Util::ComputeImageDataSizes(
10681 width, height, format, type, state_.unpack_alignment, &data_size,
10683 return error::kOutOfBounds;
10685 const void* pixels = GetSharedMemoryAs<const void*>(
10686 c.data_shm_id, c.data_shm_offset, data_size);
10688 // All the normal glTexSubImage2D validation.
10689 error::Error error = error::kNoError;
10690 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10691 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10695 // Extra async validation.
10696 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10698 Texture* texture = texture_ref->texture();
10699 if (!ValidateAsyncTransfer(
10700 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10701 return error::kNoError;
10703 // Guarantee async textures are always 'cleared' as follows:
10704 // - AsyncTexImage2D can not redefine an existing texture
10705 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10706 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10707 // - Textures become immutable after an async call.
10708 // This way we know in all cases that an async texture is always clear.
10709 if (!texture->SafeToRenderFrom()) {
10710 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10712 LOCAL_SET_GL_ERROR(
10714 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10715 return error::kNoError;
10719 // Setup the parameters.
10720 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10721 width, height, format, type};
10722 AsyncMemoryParams mem_params(
10723 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
10724 AsyncPixelTransferDelegate* delegate =
10725 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10727 // TODO(epenner): We may want to enforce exclusive use
10728 // of async APIs in which case this should become an error,
10729 // (the texture should have been async defined).
10730 AsyncTexImage2DParams define_params = {target, level,
10732 texture->GetLevelSize(target, level, &define_params.width,
10733 &define_params.height);
10734 texture->GetLevelType(target, level, &define_params.type,
10735 &define_params.internal_format);
10736 // Set up the async state if needed, and make the texture
10737 // immutable so the async state stays valid.
10738 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10739 texture_ref, define_params);
10740 texture->SetImmutable(true);
10743 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10744 return error::kNoError;
10747 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10748 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10749 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10750 GLenum target = static_cast<GLenum>(c.target);
10752 if (GL_TEXTURE_2D != target) {
10753 LOCAL_SET_GL_ERROR(
10754 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10755 return error::kNoError;
10757 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10759 if (!texture_ref) {
10760 LOCAL_SET_GL_ERROR(
10761 GL_INVALID_OPERATION,
10762 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10763 return error::kNoError;
10765 AsyncPixelTransferDelegate* delegate =
10766 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10768 LOCAL_SET_GL_ERROR(
10769 GL_INVALID_OPERATION,
10770 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10771 return error::kNoError;
10773 delegate->WaitForTransferCompletion();
10774 ProcessFinishedAsyncTransfers();
10775 return error::kNoError;
10778 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
10779 uint32 immediate_data_size, const cmds::WaitAllAsyncTexImage2DCHROMIUM& c) {
10780 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10782 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
10783 ProcessFinishedAsyncTransfers();
10784 return error::kNoError;
10787 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10788 TextureRef* texture_ref) {
10789 Texture* texture = texture_ref->texture();
10790 DoDidUseTexImageIfNeeded(texture, texture->target());
10793 void GLES2DecoderImpl::OnOutOfMemoryError() {
10794 if (lose_context_when_out_of_memory_) {
10795 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
10796 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB);
10800 // Include the auto-generated part of this file. We split this because it means
10801 // we can easily edit the non-auto generated parts right here in this file
10802 // instead of having to edit some template or the code generator.
10803 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10805 } // namespace gles2