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/command_line.h"
19 #include "base/debug/trace_event.h"
20 #include "base/debug/trace_event_synthetic_delay.h"
21 #include "base/memory/scoped_ptr.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_split.h"
24 #include "build/build_config.h"
25 #define GLES2_GPU_SERVICE 1
26 #include "gpu/command_buffer/common/debug_marker_manager.h"
27 #include "gpu/command_buffer/common/gles2_cmd_format.h"
28 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
29 #include "gpu/command_buffer/common/id_allocator.h"
30 #include "gpu/command_buffer/common/mailbox.h"
31 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
32 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
33 #include "gpu/command_buffer/service/buffer_manager.h"
34 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
35 #include "gpu/command_buffer/service/context_group.h"
36 #include "gpu/command_buffer/service/context_state.h"
37 #include "gpu/command_buffer/service/error_state.h"
38 #include "gpu/command_buffer/service/feature_info.h"
39 #include "gpu/command_buffer/service/framebuffer_manager.h"
40 #include "gpu/command_buffer/service/gl_utils.h"
41 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
42 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
43 #include "gpu/command_buffer/service/gpu_state_tracer.h"
44 #include "gpu/command_buffer/service/gpu_switches.h"
45 #include "gpu/command_buffer/service/gpu_tracer.h"
46 #include "gpu/command_buffer/service/image_manager.h"
47 #include "gpu/command_buffer/service/mailbox_manager.h"
48 #include "gpu/command_buffer/service/memory_tracking.h"
49 #include "gpu/command_buffer/service/program_manager.h"
50 #include "gpu/command_buffer/service/query_manager.h"
51 #include "gpu/command_buffer/service/renderbuffer_manager.h"
52 #include "gpu/command_buffer/service/shader_manager.h"
53 #include "gpu/command_buffer/service/shader_translator.h"
54 #include "gpu/command_buffer/service/shader_translator_cache.h"
55 #include "gpu/command_buffer/service/texture_manager.h"
56 #include "gpu/command_buffer/service/vertex_array_manager.h"
57 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
58 #include "ui/gl/gl_bindings.h"
59 #include "ui/gl/gl_fence.h"
60 #include "ui/gl/gl_image.h"
61 #include "ui/gl/gl_implementation.h"
62 #include "ui/gl/gl_surface.h"
64 #if defined(OS_MACOSX)
65 #include "ui/gl/io_surface_support_mac.h"
69 #include "base/win/win_util.h"
72 // TODO(zmo): we can't include "City.h" due to type def conflicts.
73 extern uint64 CityHash64(const char*, size_t);
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";
84 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
85 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
86 return static_cast<khronos_uint64_t>(
87 CityHash64(name, static_cast<size_t>(len)));
91 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
94 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
97 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
98 GLenum precision_type,
99 GLint *range, GLint *precision) {
100 switch (precision_type) {
104 // These values are for a 32-bit twos-complement integer format.
110 case GL_MEDIUM_FLOAT:
112 // These values are for an IEEE single-precision floating-point format.
122 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
123 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
124 // This function is sometimes defined even though it's really just
125 // a stub, so we need to set range and precision as if it weren't
126 // defined before calling it.
127 // On Mac OS with some GPUs, calling this generates a
128 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
130 glGetShaderPrecisionFormat(shader_type, precision_type,
133 // TODO(brianderson): Make the following official workarounds.
135 // Some drivers have bugs where they report the ranges as a negative number.
136 // Taking the absolute value here shouldn't hurt because negative numbers
137 // aren't expected anyway.
138 range[0] = abs(range[0]);
139 range[1] = abs(range[1]);
141 // If the driver reports a precision for highp float that isn't actually
142 // highp, don't pretend like it's supported because shader compilation will
144 if (precision_type == GL_HIGH_FLOAT &&
145 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
155 class GLES2DecoderImpl;
157 // Local versions of the SET_GL_ERROR macros
158 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
159 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
160 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
161 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
162 function_name, value, label)
163 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
164 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
165 function_name, pname)
166 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
167 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
169 #define LOCAL_PEEK_GL_ERROR(function_name) \
170 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
171 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
172 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
173 #define LOCAL_PERFORMANCE_WARNING(msg) \
174 PerformanceWarning(__FILE__, __LINE__, msg)
175 #define LOCAL_RENDER_WARNING(msg) \
176 RenderWarning(__FILE__, __LINE__, msg)
178 // Check that certain assumptions the code makes are true. There are places in
179 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
180 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
181 // a few others) are 32bits. If they are not 32bits the code will have to change
182 // to call those GL functions with service side memory and then copy the results
183 // to shared memory, converting the sizes.
184 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
185 GLint_not_same_size_as_uint32);
186 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
187 GLint_not_same_size_as_uint32);
188 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
189 GLfloat_not_same_size_as_float);
191 // TODO(kbr): the use of this anonymous namespace core dumps the
192 // linker on Mac OS X 10.6 when the symbol ordering file is used
195 // Returns the address of the first byte after a struct.
196 template <typename T>
197 const void* AddressAfterStruct(const T& pod) {
198 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
201 // Returns the address of the frst byte after the struct or NULL if size >
202 // immediate_data_size.
203 template <typename RETURN_TYPE, typename COMMAND_TYPE>
204 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
206 uint32 immediate_data_size) {
207 return (size <= immediate_data_size) ?
208 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
212 // Computes the data size for certain gl commands like glUniform.
213 bool ComputeDataSize(
216 unsigned int elements_per_unit,
219 if (!SafeMultiplyUint32(count, size, &value)) {
222 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
229 // A struct to hold info about each command.
231 uint8 arg_flags; // How to handle the arguments for this command
232 uint8 cmd_flags; // How to handle this command
233 uint16 arg_count; // How many arguments are expected for this command.
236 // cmds::name::cmd_flags,
237 // A table of CommandInfo for all the commands.
238 const CommandInfo g_command_info[] = {
239 #define GLES2_CMD_OP(name) { \
240 cmds::name::kArgFlags, \
241 cmds::name::cmd_flags, \
242 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
244 GLES2_COMMAND_LIST(GLES2_CMD_OP)
249 // Return true if a character belongs to the ASCII subset as defined in
250 // GLSL ES 1.0 spec section 3.1.
251 static bool CharacterIsValidForGLES(unsigned char c) {
252 // Printing characters are valid except " $ ` @ \ ' DEL.
253 if (c >= 32 && c <= 126 &&
262 // Horizontal tab, line feed, vertical tab, form feed, carriage return
264 if (c >= 9 && c <= 13) {
271 static bool StringIsValidForGLES(const char* str) {
272 for (; *str; ++str) {
273 if (!CharacterIsValidForGLES(*str)) {
280 // Wrapper for glEnable/glDisable that doesn't suck.
281 static void EnableDisable(GLenum pname, bool enable) {
289 // This class prevents any GL errors that occur when it is in scope from
290 // being reported to the client.
291 class ScopedGLErrorSuppressor {
293 explicit ScopedGLErrorSuppressor(
294 const char* function_name, ErrorState* error_state);
295 ~ScopedGLErrorSuppressor();
297 const char* function_name_;
298 ErrorState* error_state_;
299 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
302 // Temporarily changes a decoder's bound texture and restore it when this
303 // object goes out of scope. Also temporarily switches to using active texture
304 // unit zero in case the client has changed that to something invalid.
305 class ScopedTextureBinder {
307 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
308 ~ScopedTextureBinder();
311 ContextState* state_;
313 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
316 // Temporarily changes a decoder's bound render buffer and restore it when this
317 // object goes out of scope.
318 class ScopedRenderBufferBinder {
320 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
321 ~ScopedRenderBufferBinder();
324 ContextState* state_;
325 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
328 // Temporarily changes a decoder's bound frame buffer and restore it when this
329 // object goes out of scope.
330 class ScopedFrameBufferBinder {
332 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
333 ~ScopedFrameBufferBinder();
336 GLES2DecoderImpl* decoder_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
340 // Temporarily changes a decoder's bound frame buffer to a resolved version of
341 // the multisampled offscreen render buffer if that buffer is multisampled, and,
342 // if it is bound or enforce_internal_framebuffer is true. If internal is
343 // true, the resolved framebuffer is not visible to the parent.
344 class ScopedResolvedFrameBufferBinder {
346 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
347 bool enforce_internal_framebuffer,
349 ~ScopedResolvedFrameBufferBinder();
352 GLES2DecoderImpl* decoder_;
353 bool resolve_and_bind_;
354 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
357 class ScopedModifyPixels {
359 explicit ScopedModifyPixels(TextureRef* ref);
360 ~ScopedModifyPixels();
366 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
368 ref_->texture()->OnWillModifyPixels();
371 ScopedModifyPixels::~ScopedModifyPixels() {
373 ref_->texture()->OnDidModifyPixels();
376 class ScopedRenderTo {
378 explicit ScopedRenderTo(Framebuffer* framebuffer);
382 const Framebuffer* framebuffer_;
385 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
386 : framebuffer_(framebuffer) {
388 framebuffer_->OnWillRenderTo();
391 ScopedRenderTo::~ScopedRenderTo() {
393 framebuffer_->OnDidRenderTo();
396 // Encapsulates an OpenGL texture.
399 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
402 // Create a new render texture.
405 // Set the initial size and format of a render texture or resize it.
406 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
408 // Copy the contents of the currently bound frame buffer.
409 void Copy(const gfx::Size& size, GLenum format);
411 // Destroy the render texture. This must be explicitly called before
412 // destroying this object.
415 // Invalidate the texture. This can be used when a context is lost and it is
416 // not possible to make it current in order to free the resource.
423 gfx::Size size() const {
428 MemoryTypeTracker memory_tracker_;
429 ContextState* state_;
430 size_t bytes_allocated_;
433 DISALLOW_COPY_AND_ASSIGN(BackTexture);
436 // Encapsulates an OpenGL render buffer of any format.
437 class BackRenderbuffer {
439 explicit BackRenderbuffer(
440 RenderbufferManager* renderbuffer_manager,
441 MemoryTracker* memory_tracker,
442 ContextState* state);
445 // Create a new render buffer.
448 // Set the initial size and format of a render buffer or resize it.
449 bool AllocateStorage(const FeatureInfo* feature_info,
450 const gfx::Size& size,
454 // Destroy the render buffer. This must be explicitly called before destroying
458 // Invalidate the render buffer. This can be used when a context is lost and
459 // it is not possible to make it current in order to free the resource.
467 RenderbufferManager* renderbuffer_manager_;
468 MemoryTypeTracker memory_tracker_;
469 ContextState* state_;
470 size_t bytes_allocated_;
472 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
475 // Encapsulates an OpenGL frame buffer.
476 class BackFramebuffer {
478 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
481 // Create a new frame buffer.
484 // Attach a color render buffer to a frame buffer.
485 void AttachRenderTexture(BackTexture* texture);
487 // Attach a render buffer to a frame buffer. Note that this unbinds any
488 // currently bound frame buffer.
489 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
491 // Destroy the frame buffer. This must be explicitly called before destroying
495 // Invalidate the frame buffer. This can be used when a context is lost and it
496 // is not possible to make it current in order to free the resource.
499 // See glCheckFramebufferStatusEXT.
500 GLenum CheckStatus();
507 GLES2DecoderImpl* decoder_;
509 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
512 struct FenceCallback {
513 explicit FenceCallback()
514 : fence(gfx::GLFence::Create()) {
517 std::vector<base::Closure> callbacks;
518 scoped_ptr<gfx::GLFence> fence;
521 // } // anonymous namespace.
523 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
524 uint32* service_texture_id) {
528 GLES2Decoder::GLES2Decoder()
529 : initialized_(false),
531 log_commands_(false) {
534 GLES2Decoder::~GLES2Decoder() {
537 void GLES2Decoder::BeginDecoding() {}
539 void GLES2Decoder::EndDecoding() {}
541 // This class implements GLES2Decoder so we don't have to expose all the GLES2
542 // cmd stuff to outside this class.
543 class GLES2DecoderImpl : public GLES2Decoder,
544 public FramebufferManager::TextureDetachObserver {
546 explicit GLES2DecoderImpl(ContextGroup* group);
547 virtual ~GLES2DecoderImpl();
549 // Overridden from AsyncAPIInterface.
550 virtual Error DoCommand(unsigned int command,
551 unsigned int arg_count,
552 const void* args) OVERRIDE;
554 // Overridden from AsyncAPIInterface.
555 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
557 // Overridden from GLES2Decoder.
558 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
559 const scoped_refptr<gfx::GLContext>& context,
561 const gfx::Size& size,
562 const DisallowedFeatures& disallowed_features,
563 const std::vector<int32>& attribs) OVERRIDE;
564 virtual void Destroy(bool have_context) OVERRIDE;
565 virtual void SetSurface(
566 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
567 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
568 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
569 void UpdateParentTextureInfo();
570 virtual bool MakeCurrent() OVERRIDE;
571 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
572 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
573 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
574 virtual Capabilities GetCapabilities() OVERRIDE;
575 virtual void RestoreState(const ContextState* prev_state) const OVERRIDE;
577 virtual void RestoreActiveTexture() const OVERRIDE {
578 state_.RestoreActiveTexture();
580 virtual void RestoreAllTextureUnitBindings(
581 const ContextState* prev_state) const OVERRIDE {
582 state_.RestoreAllTextureUnitBindings(prev_state);
584 virtual void RestoreActiveTextureUnitBinding(
585 unsigned int target) const OVERRIDE {
586 state_.RestoreActiveTextureUnitBinding(target);
588 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
589 state_.RestoreAttribute(index);
591 virtual void RestoreBufferBindings() const OVERRIDE {
592 state_.RestoreBufferBindings();
594 virtual void RestoreGlobalState() const OVERRIDE {
595 state_.RestoreGlobalState();
597 virtual void RestoreProgramBindings() const OVERRIDE {
598 state_.RestoreProgramBindings();
600 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
601 state_.RestoreTextureUnitBindings(unit, NULL);
603 virtual void RestoreFramebufferBindings() const OVERRIDE;
604 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
606 virtual void ClearAllAttributes() const OVERRIDE;
607 virtual void RestoreAllAttributes() const OVERRIDE;
609 virtual QueryManager* GetQueryManager() OVERRIDE {
610 return query_manager_.get();
612 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
613 return vertex_array_manager_.get();
615 virtual bool ProcessPendingQueries() OVERRIDE;
616 virtual bool HasMoreIdleWork() OVERRIDE;
617 virtual void PerformIdleWork() OVERRIDE;
619 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
621 virtual void SetResizeCallback(
622 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
624 virtual Logger* GetLogger() OVERRIDE;
626 virtual void BeginDecoding() OVERRIDE;
627 virtual void EndDecoding() OVERRIDE;
629 virtual ErrorState* GetErrorState() OVERRIDE;
630 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
632 virtual void SetShaderCacheCallback(
633 const ShaderCacheCallback& callback) OVERRIDE;
634 virtual void SetWaitSyncPointCallback(
635 const WaitSyncPointCallback& callback) OVERRIDE;
637 virtual AsyncPixelTransferManager*
638 GetAsyncPixelTransferManager() OVERRIDE;
639 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
640 virtual void SetAsyncPixelTransferManagerForTest(
641 AsyncPixelTransferManager* manager) OVERRIDE;
642 void ProcessFinishedAsyncTransfers();
644 virtual bool GetServiceTextureId(uint32 client_texture_id,
645 uint32* service_texture_id) OVERRIDE;
647 virtual uint32 GetTextureUploadCount() OVERRIDE;
648 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
649 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
650 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
652 // Restores the current state to the user's settings.
653 void RestoreCurrentFramebufferBindings();
655 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
656 void ApplyDirtyState();
658 // These check the state of the currently bound framebuffer or the
659 // backbuffer if no framebuffer is bound.
660 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
661 // check with all attached and enabled color attachments.
662 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
663 bool BoundFramebufferHasDepthAttachment();
664 bool BoundFramebufferHasStencilAttachment();
666 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
668 // Overridden from FramebufferManager::TextureDetachObserver:
669 virtual void OnTextureRefDetachedFromFramebuffer(
670 TextureRef* texture) OVERRIDE;
672 // Helpers to facilitate calling into compatible extensions.
673 static void RenderbufferStorageMultisampleHelper(
674 const FeatureInfo* feature_info,
677 GLenum internal_format,
681 void BlitFramebufferHelper(GLint srcX0,
693 friend class ScopedFrameBufferBinder;
694 friend class ScopedResolvedFrameBufferBinder;
695 friend class BackFramebuffer;
697 // Initialize or re-initialize the shader translator.
698 bool InitializeShaderTranslator();
700 void UpdateCapabilities();
702 // Helpers for the glGen and glDelete functions.
703 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
704 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
705 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
706 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
707 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
708 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
709 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
710 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
711 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
712 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
713 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
714 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
717 void OnFboChanged() const;
718 void OnUseFramebuffer() const;
720 // TODO(gman): Cache these pointers?
721 BufferManager* buffer_manager() {
722 return group_->buffer_manager();
725 RenderbufferManager* renderbuffer_manager() {
726 return group_->renderbuffer_manager();
729 FramebufferManager* framebuffer_manager() {
730 return group_->framebuffer_manager();
733 ProgramManager* program_manager() {
734 return group_->program_manager();
737 ShaderManager* shader_manager() {
738 return group_->shader_manager();
741 const TextureManager* texture_manager() const {
742 return group_->texture_manager();
745 TextureManager* texture_manager() {
746 return group_->texture_manager();
749 MailboxManager* mailbox_manager() {
750 return group_->mailbox_manager();
753 ImageManager* image_manager() {
754 return group_->image_manager();
757 VertexArrayManager* vertex_array_manager() {
758 return vertex_array_manager_.get();
761 MemoryTracker* memory_tracker() {
762 return group_->memory_tracker();
765 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
766 MemoryTracker* tracker = memory_tracker();
768 return tracker->EnsureGPUMemoryAvailable(estimated_size);
773 bool IsOffscreenBufferMultisampled() const {
774 return offscreen_target_samples_ > 1;
777 // Creates a Texture for the given texture.
778 TextureRef* CreateTexture(
779 GLuint client_id, GLuint service_id) {
780 return texture_manager()->CreateTexture(client_id, service_id);
783 // Gets the texture info for the given texture. Returns NULL if none exists.
784 TextureRef* GetTexture(GLuint client_id) const {
785 return texture_manager()->GetTexture(client_id);
788 // Deletes the texture info for the given texture.
789 void RemoveTexture(GLuint client_id) {
790 texture_manager()->RemoveTexture(client_id);
793 // Get the size (in pixels) of the currently bound frame buffer (either FBO
794 // or regular back buffer).
795 gfx::Size GetBoundReadFrameBufferSize();
797 // Get the format of the currently bound frame buffer (either FBO or regular
799 GLenum GetBoundReadFrameBufferTextureType();
800 GLenum GetBoundReadFrameBufferInternalFormat();
801 GLenum GetBoundDrawFrameBufferInternalFormat();
803 // Wrapper for CompressedTexImage2D commands.
804 error::Error DoCompressedTexImage2D(
807 GLenum internal_format,
814 // Wrapper for CompressedTexSubImage2D.
815 void DoCompressedTexSubImage2D(
826 // Wrapper for CopyTexImage2D.
827 void DoCopyTexImage2D(
830 GLenum internal_format,
837 // Wrapper for SwapBuffers.
838 void DoSwapBuffers();
840 // Wrapper for CopyTexSubImage2D.
841 void DoCopyTexSubImage2D(
851 // Validation for TexSubImage2D.
852 bool ValidateTexSubImage2D(
854 const char* function_name,
865 // Wrapper for TexSubImage2D.
866 error::Error DoTexSubImage2D(
877 // Extra validation for async tex(Sub)Image2D.
878 bool ValidateAsyncTransfer(
879 const char* function_name,
880 TextureRef* texture_ref,
885 // Wrapper for TexImageIOSurface2DCHROMIUM.
886 void DoTexImageIOSurface2DCHROMIUM(
890 GLuint io_surface_id,
893 void DoCopyTextureCHROMIUM(
898 GLenum internal_format,
901 // Wrapper for TexStorage2DEXT.
902 void DoTexStorage2DEXT(
905 GLenum internal_format,
909 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
910 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
912 void DoBindTexImage2DCHROMIUM(
915 void DoReleaseTexImage2DCHROMIUM(
919 void DoTraceEndCHROMIUM(void);
921 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
923 // Creates a Program for the given program.
924 Program* CreateProgram(
925 GLuint client_id, GLuint service_id) {
926 return program_manager()->CreateProgram(client_id, service_id);
929 // Gets the program info for the given program. Returns NULL if none exists.
930 Program* GetProgram(GLuint client_id) {
931 return program_manager()->GetProgram(client_id);
935 void LogClientServiceMapping(
936 const char* /* function_name */,
937 GLuint /* client_id */,
938 GLuint /* service_id */) {
941 void LogClientServiceForInfo(
942 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
945 void LogClientServiceMapping(
946 const char* function_name, GLuint client_id, GLuint service_id) {
947 if (service_logging_) {
948 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
949 << ": client_id = " << client_id
950 << ", service_id = " << service_id;
954 void LogClientServiceForInfo(
955 T* info, GLuint client_id, const char* function_name) {
957 LogClientServiceMapping(function_name, client_id, info->service_id());
962 // Gets the program info for the given program. If it's not a program
963 // generates a GL error. Returns NULL if not program.
964 Program* GetProgramInfoNotShader(
965 GLuint client_id, const char* function_name) {
966 Program* program = GetProgram(client_id);
968 if (GetShader(client_id)) {
970 GL_INVALID_OPERATION, function_name, "shader passed for program");
972 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
975 LogClientServiceForInfo(program, client_id, function_name);
980 // Creates a Shader for the given shader.
981 Shader* CreateShader(
984 GLenum shader_type) {
985 return shader_manager()->CreateShader(
986 client_id, service_id, shader_type);
989 // Gets the shader info for the given shader. Returns NULL if none exists.
990 Shader* GetShader(GLuint client_id) {
991 return shader_manager()->GetShader(client_id);
994 // Gets the shader info for the given shader. If it's not a shader generates a
995 // GL error. Returns NULL if not shader.
996 Shader* GetShaderInfoNotProgram(
997 GLuint client_id, const char* function_name) {
998 Shader* shader = GetShader(client_id);
1000 if (GetProgram(client_id)) {
1002 GL_INVALID_OPERATION, function_name, "program passed for shader");
1005 GL_INVALID_VALUE, function_name, "unknown shader");
1008 LogClientServiceForInfo(shader, client_id, function_name);
1012 // Creates a buffer info for the given buffer.
1013 void CreateBuffer(GLuint client_id, GLuint service_id) {
1014 return buffer_manager()->CreateBuffer(client_id, service_id);
1017 // Gets the buffer info for the given buffer.
1018 Buffer* GetBuffer(GLuint client_id) {
1019 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1023 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1024 // on glDeleteBuffers so we can make sure the user does not try to render
1025 // with deleted buffers.
1026 void RemoveBuffer(GLuint client_id);
1028 // Creates a framebuffer info for the given framebuffer.
1029 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1030 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1033 // Gets the framebuffer info for the given framebuffer.
1034 Framebuffer* GetFramebuffer(GLuint client_id) {
1035 return framebuffer_manager()->GetFramebuffer(client_id);
1038 // Removes the framebuffer info for the given framebuffer.
1039 void RemoveFramebuffer(GLuint client_id) {
1040 framebuffer_manager()->RemoveFramebuffer(client_id);
1043 // Creates a renderbuffer info for the given renderbuffer.
1044 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1045 return renderbuffer_manager()->CreateRenderbuffer(
1046 client_id, service_id);
1049 // Gets the renderbuffer info for the given renderbuffer.
1050 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1051 return renderbuffer_manager()->GetRenderbuffer(client_id);
1054 // Removes the renderbuffer info for the given renderbuffer.
1055 void RemoveRenderbuffer(GLuint client_id) {
1056 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1059 // Gets the vertex attrib manager for the given vertex array.
1060 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1061 VertexAttribManager* info =
1062 vertex_array_manager()->GetVertexAttribManager(client_id);
1066 // Removes the vertex attrib manager for the given vertex array.
1067 void RemoveVertexAttribManager(GLuint client_id) {
1068 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1071 // Creates a vertex attrib manager for the given vertex array.
1072 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1073 return vertex_array_manager()->CreateVertexAttribManager(
1074 client_id, service_id, group_->max_vertex_attribs());
1077 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1078 void DoBindUniformLocationCHROMIUM(
1079 GLuint client_id, GLint location, const char* name);
1081 error::Error GetAttribLocationHelper(
1082 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1083 const std::string& name_str);
1085 error::Error GetUniformLocationHelper(
1086 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1087 const std::string& name_str);
1089 // Helper for glShaderSource.
1090 error::Error ShaderSourceHelper(
1091 GLuint client_id, const char* data, uint32 data_size);
1093 // Clear any textures used by the current program.
1094 bool ClearUnclearedTextures();
1096 // Clears any uncleared attachments attached to the given frame buffer.
1097 // Returns false if there was a generated GL error.
1098 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1100 // overridden from GLES2Decoder
1101 virtual bool ClearLevel(unsigned service_id,
1102 unsigned bind_target,
1105 unsigned internal_format,
1110 bool is_texture_immutable) OVERRIDE;
1112 // Restore all GL state that affects clearing.
1113 void RestoreClearState();
1115 // Remembers the state of some capabilities.
1116 // Returns: true if glEnable/glDisable should actually be called.
1117 bool SetCapabilityState(GLenum cap, bool enabled);
1119 // Check that the currently bound framebuffers are valid.
1120 // Generates GL error if not.
1121 bool CheckBoundFramebuffersValid(const char* func_name);
1123 // Check if a framebuffer meets our requirements.
1124 bool CheckFramebufferValid(
1125 Framebuffer* framebuffer,
1127 const char* func_name);
1129 // Checks if the current program exists and is valid. If not generates the
1130 // appropriate GL error. Returns true if the current program is in a usable
1132 bool CheckCurrentProgram(const char* function_name);
1134 // Checks if the current program exists and is valid and that location is not
1135 // -1. If the current program is not valid generates the appropriate GL
1136 // error. Returns true if the current program is in a usable state and
1137 // location is not -1.
1138 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1140 // Gets the type of a uniform for a location in the current program. Sets GL
1141 // errors if the current program is not valid. Returns true if the current
1142 // program is valid and the location exists. Adjusts count so it
1143 // does not overflow the uniform.
1144 bool PrepForSetUniformByLocation(GLint fake_location,
1145 const char* function_name,
1146 Program::UniformApiType api_type,
1147 GLint* real_location,
1151 // Gets the service id for any simulated backbuffer fbo.
1152 GLuint GetBackbufferServiceId() const;
1154 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1155 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1157 // Helper for glGetVertexAttrib
1158 void GetVertexAttribHelper(
1159 const VertexAttrib* attrib, GLenum pname, GLint* param);
1161 // Wrapper for glCreateProgram
1162 bool CreateProgramHelper(GLuint client_id);
1164 // Wrapper for glCreateShader
1165 bool CreateShaderHelper(GLenum type, GLuint client_id);
1167 // Wrapper for glActiveTexture
1168 void DoActiveTexture(GLenum texture_unit);
1170 // Wrapper for glAttachShader
1171 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1173 // Wrapper for glBindBuffer since we need to track the current targets.
1174 void DoBindBuffer(GLenum target, GLuint buffer);
1176 // Wrapper for glBindFramebuffer since we need to track the current targets.
1177 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1179 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1180 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1182 // Wrapper for glBindTexture since we need to track the current targets.
1183 void DoBindTexture(GLenum target, GLuint texture);
1185 // Wrapper for glBindVertexArrayOES
1186 void DoBindVertexArrayOES(GLuint array);
1187 void EmulateVertexArrayState();
1189 // Wrapper for glBlitFramebufferCHROMIUM.
1190 void DoBlitFramebufferCHROMIUM(
1191 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1192 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1193 GLbitfield mask, GLenum filter);
1195 // Wrapper for glBufferSubData.
1196 void DoBufferSubData(
1197 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1199 // Wrapper for glCheckFramebufferStatus
1200 GLenum DoCheckFramebufferStatus(GLenum target);
1202 // Wrapper for glClear
1203 error::Error DoClear(GLbitfield mask);
1205 // Wrappers for various state.
1206 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1207 void DoSampleCoverage(GLclampf value, GLboolean invert);
1209 // Wrapper for glCompileShader.
1210 void DoCompileShader(GLuint shader);
1212 // Helper for DeleteSharedIdsCHROMIUM commands.
1213 void DoDeleteSharedIdsCHROMIUM(
1214 GLuint namespace_id, GLsizei n, const GLuint* ids);
1216 // Wrapper for glDetachShader
1217 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1219 // Wrapper for glDisable
1220 void DoDisable(GLenum cap);
1222 // Wrapper for glDisableVertexAttribArray.
1223 void DoDisableVertexAttribArray(GLuint index);
1225 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1227 void DoDiscardFramebufferEXT(GLenum target,
1228 GLsizei numAttachments,
1229 const GLenum* attachments);
1231 // Wrapper for glEnable
1232 void DoEnable(GLenum cap);
1234 // Wrapper for glEnableVertexAttribArray.
1235 void DoEnableVertexAttribArray(GLuint index);
1237 // Wrapper for glFinish.
1240 // Wrapper for glFlush.
1243 // Wrapper for glFramebufferRenderbufffer.
1244 void DoFramebufferRenderbuffer(
1245 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1246 GLuint renderbuffer);
1248 // Wrapper for glFramebufferTexture2D.
1249 void DoFramebufferTexture2D(
1250 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1253 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1254 void DoFramebufferTexture2DMultisample(
1255 GLenum target, GLenum attachment, GLenum textarget,
1256 GLuint texture, GLint level, GLsizei samples);
1258 // Common implementation for both DoFramebufferTexture2D wrappers.
1259 void DoFramebufferTexture2DCommon(const char* name,
1260 GLenum target, GLenum attachment, GLenum textarget,
1261 GLuint texture, GLint level, GLsizei samples);
1263 // Wrapper for glGenerateMipmap
1264 void DoGenerateMipmap(GLenum target);
1266 // Helper for GenSharedIdsCHROMIUM commands.
1267 void DoGenSharedIdsCHROMIUM(
1268 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1270 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1271 // to account for different pname values defined in different extension
1273 GLenum AdjustGetPname(GLenum pname);
1275 // Wrapper for DoGetBooleanv.
1276 void DoGetBooleanv(GLenum pname, GLboolean* params);
1278 // Wrapper for DoGetFloatv.
1279 void DoGetFloatv(GLenum pname, GLfloat* params);
1281 // Wrapper for glGetFramebufferAttachmentParameteriv.
1282 void DoGetFramebufferAttachmentParameteriv(
1283 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1285 // Wrapper for glGetIntegerv.
1286 void DoGetIntegerv(GLenum pname, GLint* params);
1288 // Gets the max value in a range in a buffer.
1289 GLuint DoGetMaxValueInBufferCHROMIUM(
1290 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1292 // Wrapper for glGetBufferParameteriv.
1293 void DoGetBufferParameteriv(
1294 GLenum target, GLenum pname, GLint* params);
1296 // Wrapper for glGetProgramiv.
1297 void DoGetProgramiv(
1298 GLuint program_id, GLenum pname, GLint* params);
1300 // Wrapper for glRenderbufferParameteriv.
1301 void DoGetRenderbufferParameteriv(
1302 GLenum target, GLenum pname, GLint* params);
1304 // Wrapper for glGetShaderiv
1305 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1307 // Wrappers for glGetTexParameter.
1308 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1309 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1310 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1312 // Wrappers for glGetVertexAttrib.
1313 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1314 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1316 // Wrappers for glIsXXX functions.
1317 bool DoIsEnabled(GLenum cap);
1318 bool DoIsBuffer(GLuint client_id);
1319 bool DoIsFramebuffer(GLuint client_id);
1320 bool DoIsProgram(GLuint client_id);
1321 bool DoIsRenderbuffer(GLuint client_id);
1322 bool DoIsShader(GLuint client_id);
1323 bool DoIsTexture(GLuint client_id);
1324 bool DoIsVertexArrayOES(GLuint client_id);
1326 // Wrapper for glLinkProgram
1327 void DoLinkProgram(GLuint program);
1329 // Helper for RegisterSharedIdsCHROMIUM.
1330 void DoRegisterSharedIdsCHROMIUM(
1331 GLuint namespace_id, GLsizei n, const GLuint* ids);
1333 // Wrapper for glRenderbufferStorage.
1334 void DoRenderbufferStorage(
1335 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1337 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1338 void DoRenderbufferStorageMultisampleCHROMIUM(
1339 GLenum target, GLsizei samples, GLenum internalformat,
1340 GLsizei width, GLsizei height);
1342 // Handler for glRenderbufferStorageMultisampleEXT
1343 // (multisampled_render_to_texture).
1344 void DoRenderbufferStorageMultisampleEXT(
1345 GLenum target, GLsizei samples, GLenum internalformat,
1346 GLsizei width, GLsizei height);
1348 // Common validation for multisample extensions.
1349 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1350 GLenum internalformat,
1354 // Verifies that the currently bound multisample renderbuffer is valid
1355 // Very slow! Only done on platforms with driver bugs that return invalid
1356 // buffers under memory pressure
1357 bool VerifyMultisampleRenderbufferIntegrity(
1358 GLuint renderbuffer, GLenum format);
1360 // Wrapper for glReleaseShaderCompiler.
1361 void DoReleaseShaderCompiler() { }
1363 // Wrappers for glTexParameter functions.
1364 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1365 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1366 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1367 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1369 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1370 // spec only these 2 functions can be used to set sampler uniforms.
1371 void DoUniform1i(GLint fake_location, GLint v0);
1372 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1373 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1374 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1375 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1377 // Wrappers for glUniformfv because some drivers don't correctly accept
1379 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1380 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1381 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1382 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1384 void DoUniformMatrix2fv(
1385 GLint fake_location, GLsizei count, GLboolean transpose,
1386 const GLfloat* value);
1387 void DoUniformMatrix3fv(
1388 GLint fake_location, GLsizei count, GLboolean transpose,
1389 const GLfloat* value);
1390 void DoUniformMatrix4fv(
1391 GLint fake_location, GLsizei count, GLboolean transpose,
1392 const GLfloat* value);
1394 bool SetVertexAttribValue(
1395 const char* function_name, GLuint index, const GLfloat* value);
1397 // Wrappers for glVertexAttrib??
1398 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1399 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1400 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1401 void DoVertexAttrib4f(
1402 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1403 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1404 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1405 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1406 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1408 // Wrapper for glViewport
1409 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1411 // Wrapper for glUseProgram
1412 void DoUseProgram(GLuint program);
1414 // Wrapper for glValidateProgram.
1415 void DoValidateProgram(GLuint program_client_id);
1417 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1418 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1419 void DoPopGroupMarkerEXT(void);
1421 // Gets the number of values that will be returned by glGetXXX. Returns
1422 // false if pname is unknown.
1423 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1425 // Checks if the current program and vertex attributes are valid for drawing.
1427 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1429 // Returns true if successful, simulated will be true if attrib0 was
1431 bool SimulateAttrib0(
1432 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1433 void RestoreStateForAttrib(GLuint attrib);
1435 // If an image is bound to texture, this will call Will/DidUseTexImage
1437 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1438 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1440 // Returns false if textures were replaced.
1441 bool PrepareTexturesForRender();
1442 void RestoreStateForTextures();
1444 // Returns true if GL_FIXED attribs were simulated.
1445 bool SimulateFixedAttribs(
1446 const char* function_name,
1447 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1448 void RestoreStateForSimulatedFixedAttribs();
1450 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1451 // cases (primcount is 0 for non-instanced).
1452 error::Error DoDrawArrays(
1453 const char* function_name,
1454 bool instanced, GLenum mode, GLint first, GLsizei count,
1456 error::Error DoDrawElements(
1457 const char* function_name,
1458 bool instanced, GLenum mode, GLsizei count, GLenum type,
1459 int32 offset, GLsizei primcount);
1461 GLenum GetBindTargetForSamplerType(GLenum type) {
1462 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1463 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1466 return GL_TEXTURE_2D;
1467 case GL_SAMPLER_CUBE:
1468 return GL_TEXTURE_CUBE_MAP;
1469 case GL_SAMPLER_EXTERNAL_OES:
1470 return GL_TEXTURE_EXTERNAL_OES;
1471 case GL_SAMPLER_2D_RECT_ARB:
1472 return GL_TEXTURE_RECTANGLE_ARB;
1479 // Gets the framebuffer info for a particular target.
1480 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1481 Framebuffer* framebuffer = NULL;
1483 case GL_FRAMEBUFFER:
1484 case GL_DRAW_FRAMEBUFFER_EXT:
1485 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1487 case GL_READ_FRAMEBUFFER_EXT:
1488 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1497 Renderbuffer* GetRenderbufferInfoForTarget(
1499 Renderbuffer* renderbuffer = NULL;
1501 case GL_RENDERBUFFER:
1502 renderbuffer = state_.bound_renderbuffer.get();
1508 return renderbuffer;
1511 // Validates the program and location for a glGetUniform call and returns
1512 // a SizeResult setup to receive the result. Returns true if glGetUniform
1513 // should be called.
1514 bool GetUniformSetup(
1515 GLuint program, GLint fake_location,
1516 uint32 shm_id, uint32 shm_offset,
1517 error::Error* error, GLint* real_location, GLuint* service_id,
1518 void** result, GLenum* result_type);
1520 virtual bool WasContextLost() OVERRIDE;
1521 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1522 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1524 #if defined(OS_MACOSX)
1525 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1528 bool ValidateCompressedTexDimensions(
1529 const char* function_name,
1530 GLint level, GLsizei width, GLsizei height, GLenum format);
1531 bool ValidateCompressedTexFuncData(
1532 const char* function_name,
1533 GLsizei width, GLsizei height, GLenum format, size_t size);
1534 bool ValidateCompressedTexSubDimensions(
1535 const char* function_name,
1536 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1537 GLsizei width, GLsizei height, GLenum format,
1540 void RenderWarning(const char* filename, int line, const std::string& msg);
1541 void PerformanceWarning(
1542 const char* filename, int line, const std::string& msg);
1544 const FeatureInfo::FeatureFlags& features() const {
1545 return feature_info_->feature_flags();
1548 const FeatureInfo::Workarounds& workarounds() const {
1549 return feature_info_->workarounds();
1552 bool ShouldDeferDraws() {
1553 return !offscreen_target_frame_buffer_.get() &&
1554 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1555 surface_->DeferDraws();
1558 bool ShouldDeferReads() {
1559 return !offscreen_target_frame_buffer_.get() &&
1560 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1561 surface_->DeferDraws();
1564 error::Error WillAccessBoundFramebufferForDraw() {
1565 if (ShouldDeferDraws())
1566 return error::kDeferCommandUntilLater;
1567 if (!offscreen_target_frame_buffer_.get() &&
1568 !framebuffer_state_.bound_draw_framebuffer.get() &&
1569 !surface_->SetBackbufferAllocation(true))
1570 return error::kLostContext;
1571 return error::kNoError;
1574 error::Error WillAccessBoundFramebufferForRead() {
1575 if (ShouldDeferReads())
1576 return error::kDeferCommandUntilLater;
1577 if (!offscreen_target_frame_buffer_.get() &&
1578 !framebuffer_state_.bound_read_framebuffer.get() &&
1579 !surface_->SetBackbufferAllocation(true))
1580 return error::kLostContext;
1581 return error::kNoError;
1584 void ProcessPendingReadPixels();
1585 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1587 // Generate a member function prototype for each command in an automated and
1589 #define GLES2_CMD_OP(name) \
1590 Error Handle ## name( \
1591 uint32 immediate_data_size, \
1592 const cmds::name& args); \
1594 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1598 // The GL context this decoder renders to on behalf of the client.
1599 scoped_refptr<gfx::GLSurface> surface_;
1600 scoped_refptr<gfx::GLContext> context_;
1602 // The ContextGroup for this decoder uses to track resources.
1603 scoped_refptr<ContextGroup> group_;
1605 DebugMarkerManager debug_marker_manager_;
1608 // All the state for this context.
1609 ContextState state_;
1611 // Current width and height of the offscreen frame buffer.
1612 gfx::Size offscreen_size_;
1614 // Util to help with GL.
1617 // unpack flip y as last set by glPixelStorei
1618 bool unpack_flip_y_;
1620 // unpack (un)premultiply alpha as last set by glPixelStorei
1621 bool unpack_premultiply_alpha_;
1622 bool unpack_unpremultiply_alpha_;
1624 // Default vertex attribs manager, used when no VAOs are bound.
1625 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
1627 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1628 GLuint attrib_0_buffer_id_;
1630 // The value currently in attrib_0.
1631 Vec4 attrib_0_value_;
1633 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1634 bool attrib_0_buffer_matches_value_;
1636 // The size of attrib 0.
1637 GLsizei attrib_0_size_;
1639 // The buffer used to simulate GL_FIXED attribs.
1640 GLuint fixed_attrib_buffer_id_;
1642 // The size of fiixed attrib buffer.
1643 GLsizei fixed_attrib_buffer_size_;
1645 // The offscreen frame buffer that the client renders to. With EGL, the
1646 // depth and stencil buffers are separate. With regular GL there is a single
1647 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1648 // offscreen_target_stencil_render_buffer_ is unused.
1649 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1650 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1651 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1652 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1653 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1654 GLenum offscreen_target_color_format_;
1655 GLenum offscreen_target_depth_format_;
1656 GLenum offscreen_target_stencil_format_;
1657 GLsizei offscreen_target_samples_;
1658 GLboolean offscreen_target_buffer_preserved_;
1660 // The copy that is saved when SwapBuffers is called.
1661 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1662 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1663 scoped_refptr<TextureRef>
1664 offscreen_saved_color_texture_info_;
1666 // The copy that is used as the destination for multi-sample resolves.
1667 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1668 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1669 GLenum offscreen_saved_color_format_;
1671 scoped_ptr<QueryManager> query_manager_;
1673 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1675 base::Callback<void(gfx::Size, float)> resize_callback_;
1677 WaitSyncPointCallback wait_sync_point_callback_;
1679 ShaderCacheCallback shader_cache_callback_;
1681 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1683 // The format of the back buffer_
1684 GLenum back_buffer_color_format_;
1685 bool back_buffer_has_depth_;
1686 bool back_buffer_has_stencil_;
1688 // Backbuffer attachments that are currently undefined.
1689 uint32 backbuffer_needs_clear_bits_;
1691 // The current decoder error.
1692 error::Error current_decoder_error_;
1694 bool use_shader_translator_;
1695 scoped_refptr<ShaderTranslator> vertex_translator_;
1696 scoped_refptr<ShaderTranslator> fragment_translator_;
1698 DisallowedFeatures disallowed_features_;
1700 // Cached from ContextGroup
1701 const Validators* validators_;
1702 scoped_refptr<FeatureInfo> feature_info_;
1706 bool has_robustness_extension_;
1707 GLenum reset_status_;
1708 bool reset_by_robustness_extension_;
1709 bool supports_post_sub_buffer_;
1711 // These flags are used to override the state of the shared feature_info_
1712 // member. Because the same FeatureInfo instance may be shared among many
1713 // contexts, the assumptions on the availablity of extensions in WebGL
1714 // contexts may be broken. These flags override the shared state to preserve
1716 bool force_webgl_glsl_validation_;
1717 bool derivatives_explicitly_enabled_;
1718 bool frag_depth_explicitly_enabled_;
1719 bool draw_buffers_explicitly_enabled_;
1721 bool compile_shader_always_succeeds_;
1724 bool service_logging_;
1726 #if defined(OS_MACOSX)
1727 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1728 TextureToIOSurfaceMap texture_to_io_surface_map_;
1731 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1733 // Cached values of the currently assigned viewport dimensions.
1734 GLsizei viewport_max_width_;
1735 GLsizei viewport_max_height_;
1737 // Command buffer stats.
1738 base::TimeDelta total_processing_commands_time_;
1740 // States related to each manager.
1741 DecoderTextureState texture_state_;
1742 DecoderFramebufferState framebuffer_state_;
1744 scoped_ptr<GPUTracer> gpu_tracer_;
1745 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1746 int gpu_trace_level_;
1747 bool gpu_trace_commands_;
1749 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1751 // Used to validate multisample renderbuffers if needed
1752 GLuint validation_texture_;
1753 GLuint validation_fbo_multisample_;
1754 GLuint validation_fbo_;
1756 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1759 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1760 const char* function_name, ErrorState* error_state)
1761 : function_name_(function_name),
1762 error_state_(error_state) {
1763 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1766 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1767 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1770 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1771 TextureUnit& info = state->texture_units[0];
1773 scoped_refptr<TextureRef> texture_ref;
1776 texture_ref = info.bound_texture_2d;
1778 case GL_TEXTURE_CUBE_MAP:
1779 texture_ref = info.bound_texture_cube_map;
1781 case GL_TEXTURE_EXTERNAL_OES:
1782 texture_ref = info.bound_texture_external_oes;
1784 case GL_TEXTURE_RECTANGLE_ARB:
1785 texture_ref = info.bound_texture_rectangle_arb;
1791 if (texture_ref.get()) {
1792 last_id = texture_ref->service_id();
1797 glBindTexture(target, last_id);
1798 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1801 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1806 ScopedGLErrorSuppressor suppressor(
1807 "ScopedTextureBinder::ctor", state_->GetErrorState());
1809 // TODO(apatrick): Check if there are any other states that need to be reset
1810 // before binding a new texture.
1811 glActiveTexture(GL_TEXTURE0);
1812 glBindTexture(target, id);
1815 ScopedTextureBinder::~ScopedTextureBinder() {
1816 ScopedGLErrorSuppressor suppressor(
1817 "ScopedTextureBinder::dtor", state_->GetErrorState());
1818 RestoreCurrentTextureBindings(state_, target_);
1821 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1824 ScopedGLErrorSuppressor suppressor(
1825 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1826 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1829 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1830 ScopedGLErrorSuppressor suppressor(
1831 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1832 state_->RestoreRenderbufferBindings();
1835 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1837 : decoder_(decoder) {
1838 ScopedGLErrorSuppressor suppressor(
1839 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1840 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1841 decoder->OnFboChanged();
1844 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1845 ScopedGLErrorSuppressor suppressor(
1846 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1847 decoder_->RestoreCurrentFramebufferBindings();
1850 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1851 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1852 : decoder_(decoder) {
1853 resolve_and_bind_ = (
1854 decoder_->offscreen_target_frame_buffer_.get() &&
1855 decoder_->IsOffscreenBufferMultisampled() &&
1856 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1857 enforce_internal_framebuffer));
1858 if (!resolve_and_bind_)
1861 ScopedGLErrorSuppressor suppressor(
1862 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1863 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1864 decoder_->offscreen_target_frame_buffer_->id());
1867 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1868 decoder_->offscreen_resolved_frame_buffer_.reset(
1869 new BackFramebuffer(decoder_));
1870 decoder_->offscreen_resolved_frame_buffer_->Create();
1871 decoder_->offscreen_resolved_color_texture_.reset(
1872 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1873 decoder_->offscreen_resolved_color_texture_->Create();
1875 DCHECK(decoder_->offscreen_saved_color_format_);
1876 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1877 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1879 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1880 decoder_->offscreen_resolved_color_texture_.get());
1881 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1882 GL_FRAMEBUFFER_COMPLETE) {
1883 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1884 << "because offscreen resolved FBO was incomplete.";
1888 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1890 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1892 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1893 const int width = decoder_->offscreen_size_.width();
1894 const int height = decoder_->offscreen_size_.height();
1895 glDisable(GL_SCISSOR_TEST);
1896 decoder->BlitFramebufferHelper(0,
1904 GL_COLOR_BUFFER_BIT,
1906 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1909 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1910 if (!resolve_and_bind_)
1913 ScopedGLErrorSuppressor suppressor(
1914 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1915 decoder_->RestoreCurrentFramebufferBindings();
1916 if (decoder_->state_.enable_flags.scissor_test) {
1917 glEnable(GL_SCISSOR_TEST);
1921 BackTexture::BackTexture(
1922 MemoryTracker* memory_tracker,
1923 ContextState* state)
1924 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1926 bytes_allocated_(0),
1930 BackTexture::~BackTexture() {
1931 // This does not destroy the render texture because that would require that
1932 // the associated GL context was current. Just check that it was explicitly
1937 void BackTexture::Create() {
1938 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1939 state_->GetErrorState());
1941 glGenTextures(1, &id_);
1942 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1943 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1944 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1945 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1946 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1948 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1949 // never called on an offscreen context, no data will ever be uploaded to the
1950 // saved offscreen color texture (it is deferred until to when SwapBuffers
1951 // is called). My idea is that some nvidia drivers might have a bug where
1952 // deleting a texture that has never been populated might cause a
1955 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1957 bytes_allocated_ = 16u * 16u * 4u;
1958 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1961 bool BackTexture::AllocateStorage(
1962 const gfx::Size& size, GLenum format, bool zero) {
1964 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
1965 state_->GetErrorState());
1966 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1967 uint32 image_size = 0;
1968 GLES2Util::ComputeImageDataSizes(
1969 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1972 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1976 scoped_ptr<char[]> zero_data;
1978 zero_data.reset(new char[image_size]);
1979 memset(zero_data.get(), 0, image_size);
1982 glTexImage2D(GL_TEXTURE_2D,
1994 bool success = glGetError() == GL_NO_ERROR;
1996 memory_tracker_.TrackMemFree(bytes_allocated_);
1997 bytes_allocated_ = image_size;
1998 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2003 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2005 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2006 state_->GetErrorState());
2007 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2008 glCopyTexImage2D(GL_TEXTURE_2D,
2017 void BackTexture::Destroy() {
2019 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2020 state_->GetErrorState());
2021 glDeleteTextures(1, &id_);
2024 memory_tracker_.TrackMemFree(bytes_allocated_);
2025 bytes_allocated_ = 0;
2028 void BackTexture::Invalidate() {
2032 BackRenderbuffer::BackRenderbuffer(
2033 RenderbufferManager* renderbuffer_manager,
2034 MemoryTracker* memory_tracker,
2035 ContextState* state)
2036 : renderbuffer_manager_(renderbuffer_manager),
2037 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2039 bytes_allocated_(0),
2043 BackRenderbuffer::~BackRenderbuffer() {
2044 // This does not destroy the render buffer because that would require that
2045 // the associated GL context was current. Just check that it was explicitly
2050 void BackRenderbuffer::Create() {
2051 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2052 state_->GetErrorState());
2054 glGenRenderbuffersEXT(1, &id_);
2057 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2058 const gfx::Size& size,
2061 ScopedGLErrorSuppressor suppressor(
2062 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2063 ScopedRenderBufferBinder binder(state_, id_);
2065 uint32 estimated_size = 0;
2066 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2067 size.width(), size.height(), samples, format, &estimated_size)) {
2071 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2076 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2081 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2088 bool success = glGetError() == GL_NO_ERROR;
2090 // Mark the previously allocated bytes as free.
2091 memory_tracker_.TrackMemFree(bytes_allocated_);
2092 bytes_allocated_ = estimated_size;
2093 // Track the newly allocated bytes.
2094 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2099 void BackRenderbuffer::Destroy() {
2101 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2102 state_->GetErrorState());
2103 glDeleteRenderbuffersEXT(1, &id_);
2106 memory_tracker_.TrackMemFree(bytes_allocated_);
2107 bytes_allocated_ = 0;
2110 void BackRenderbuffer::Invalidate() {
2114 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2115 : decoder_(decoder),
2119 BackFramebuffer::~BackFramebuffer() {
2120 // This does not destroy the frame buffer because that would require that
2121 // the associated GL context was current. Just check that it was explicitly
2126 void BackFramebuffer::Create() {
2127 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2128 decoder_->GetErrorState());
2130 glGenFramebuffersEXT(1, &id_);
2133 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2135 ScopedGLErrorSuppressor suppressor(
2136 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2137 ScopedFrameBufferBinder binder(decoder_, id_);
2138 GLuint attach_id = texture ? texture->id() : 0;
2139 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2140 GL_COLOR_ATTACHMENT0,
2146 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2147 BackRenderbuffer* render_buffer) {
2149 ScopedGLErrorSuppressor suppressor(
2150 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2151 ScopedFrameBufferBinder binder(decoder_, id_);
2152 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2153 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2159 void BackFramebuffer::Destroy() {
2161 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2162 decoder_->GetErrorState());
2163 glDeleteFramebuffersEXT(1, &id_);
2168 void BackFramebuffer::Invalidate() {
2172 GLenum BackFramebuffer::CheckStatus() {
2174 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2175 decoder_->GetErrorState());
2176 ScopedFrameBufferBinder binder(decoder_, id_);
2177 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2180 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2181 return new GLES2DecoderImpl(group);
2184 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2187 logger_(&debug_marker_manager_),
2188 state_(group_->feature_info(), &logger_),
2189 unpack_flip_y_(false),
2190 unpack_premultiply_alpha_(false),
2191 unpack_unpremultiply_alpha_(false),
2192 attrib_0_buffer_id_(0),
2193 attrib_0_buffer_matches_value_(true),
2195 fixed_attrib_buffer_id_(0),
2196 fixed_attrib_buffer_size_(0),
2197 offscreen_target_color_format_(0),
2198 offscreen_target_depth_format_(0),
2199 offscreen_target_stencil_format_(0),
2200 offscreen_target_samples_(0),
2201 offscreen_target_buffer_preserved_(true),
2202 offscreen_saved_color_format_(0),
2203 back_buffer_color_format_(0),
2204 back_buffer_has_depth_(false),
2205 back_buffer_has_stencil_(false),
2206 backbuffer_needs_clear_bits_(0),
2207 current_decoder_error_(error::kNoError),
2208 use_shader_translator_(true),
2209 validators_(group_->feature_info()->validators()),
2210 feature_info_(group_->feature_info()),
2212 has_robustness_extension_(false),
2213 reset_status_(GL_NO_ERROR),
2214 reset_by_robustness_extension_(false),
2215 supports_post_sub_buffer_(false),
2216 force_webgl_glsl_validation_(false),
2217 derivatives_explicitly_enabled_(false),
2218 frag_depth_explicitly_enabled_(false),
2219 draw_buffers_explicitly_enabled_(false),
2220 compile_shader_always_succeeds_(false),
2221 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2222 switches::kEnableGPUServiceLoggingGPU)),
2223 viewport_max_width_(0),
2224 viewport_max_height_(0),
2225 texture_state_(group_->feature_info()
2227 .texsubimage2d_faster_than_teximage2d),
2228 validation_texture_(0),
2229 validation_fbo_multisample_(0),
2230 validation_fbo_(0) {
2233 attrib_0_value_.v[0] = 0.0f;
2234 attrib_0_value_.v[1] = 0.0f;
2235 attrib_0_value_.v[2] = 0.0f;
2236 attrib_0_value_.v[3] = 1.0f;
2238 // The shader translator is used for WebGL even when running on EGL
2239 // because additional restrictions are needed (like only enabling
2240 // GL_OES_standard_derivatives on demand). It is used for the unit
2241 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2242 // the empty string to CompileShader and this is not a valid shader.
2243 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2244 CommandLine::ForCurrentProcess()->HasSwitch(
2245 switches::kDisableGLSLTranslator)) {
2246 use_shader_translator_ = false;
2250 GLES2DecoderImpl::~GLES2DecoderImpl() {
2253 bool GLES2DecoderImpl::Initialize(
2254 const scoped_refptr<gfx::GLSurface>& surface,
2255 const scoped_refptr<gfx::GLContext>& context,
2257 const gfx::Size& size,
2258 const DisallowedFeatures& disallowed_features,
2259 const std::vector<int32>& attribs) {
2260 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2261 DCHECK(context->IsCurrent(surface.get()));
2262 DCHECK(!context_.get());
2265 gpu_tracer_ = GPUTracer::Create(this);
2266 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2267 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2268 gpu_trace_level_ = 2;
2269 gpu_trace_commands_ = false;
2271 if (CommandLine::ForCurrentProcess()->HasSwitch(
2272 switches::kEnableGPUDebugging)) {
2276 if (CommandLine::ForCurrentProcess()->HasSwitch(
2277 switches::kEnableGPUCommandLogging)) {
2278 set_log_commands(true);
2281 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2282 switches::kCompileShaderAlwaysSucceeds);
2285 // Take ownership of the context and surface. The surface can be replaced with
2290 ContextCreationAttribHelper attrib_parser;
2291 if (!attrib_parser.Parse(attribs))
2294 // If the failIfMajorPerformanceCaveat context creation attribute was true
2295 // and we are using a software renderer, fail.
2296 if (attrib_parser.fail_if_major_perf_caveat_ &&
2297 feature_info_->feature_flags().is_swiftshader) {
2298 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2303 if (!group_->Initialize(this, disallowed_features)) {
2304 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2305 << "failed to initialize.";
2306 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2312 disallowed_features_ = disallowed_features;
2314 state_.attrib_values.resize(group_->max_vertex_attribs());
2315 default_vertex_attrib_manager_ = new VertexAttribManager();
2316 default_vertex_attrib_manager_->Initialize(
2317 group_->max_vertex_attribs(),
2318 feature_info_->workarounds().init_vertex_attributes);
2320 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2321 DoBindVertexArrayOES(0);
2323 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2324 vertex_array_manager_.reset(new VertexArrayManager());
2326 util_.set_num_compressed_texture_formats(
2327 validators_->compressed_texture_format.GetValues().size());
2329 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2330 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2331 // OpenGL ES 2.0 does not have this issue.
2332 glEnableVertexAttribArray(0);
2334 glGenBuffersARB(1, &attrib_0_buffer_id_);
2335 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2336 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2337 glBindBuffer(GL_ARRAY_BUFFER, 0);
2338 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2340 state_.texture_units.resize(group_->max_texture_units());
2341 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2342 glActiveTexture(GL_TEXTURE0 + tt);
2343 // We want the last bind to be 2D.
2345 if (features().oes_egl_image_external) {
2346 ref = texture_manager()->GetDefaultTextureInfo(
2347 GL_TEXTURE_EXTERNAL_OES);
2348 state_.texture_units[tt].bound_texture_external_oes = ref;
2349 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
2351 if (features().arb_texture_rectangle) {
2352 ref = texture_manager()->GetDefaultTextureInfo(
2353 GL_TEXTURE_RECTANGLE_ARB);
2354 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2355 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
2357 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2358 state_.texture_units[tt].bound_texture_cube_map = ref;
2359 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2360 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2361 state_.texture_units[tt].bound_texture_2d = ref;
2362 glBindTexture(GL_TEXTURE_2D, ref->service_id());
2364 glActiveTexture(GL_TEXTURE0);
2368 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2369 features().chromium_framebuffer_multisample) {
2370 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2371 // max_sample_count must be initialized to a sane value. If
2372 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2373 GLint max_sample_count = 1;
2374 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2375 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2378 offscreen_target_samples_ = 1;
2380 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2382 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2383 const bool rgb8_supported =
2384 context_->HasExtension("GL_OES_rgb8_rgba8");
2385 // The only available default render buffer formats in GLES2 have very
2386 // little precision. Don't enable multisampling unless 8-bit render
2387 // buffer formats are available--instead fall back to 8-bit textures.
2388 if (rgb8_supported && offscreen_target_samples_ > 1) {
2389 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2392 offscreen_target_samples_ = 1;
2393 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2397 // ANGLE only supports packed depth/stencil formats, so use it if it is
2399 const bool depth24_stencil8_supported =
2400 feature_info_->feature_flags().packed_depth24_stencil8;
2401 VLOG(1) << "GL_OES_packed_depth_stencil "
2402 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2403 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2404 depth24_stencil8_supported) {
2405 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2406 offscreen_target_stencil_format_ = 0;
2408 // It may be the case that this depth/stencil combination is not
2409 // supported, but this will be checked later by CheckFramebufferStatus.
2410 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2411 GL_DEPTH_COMPONENT16 : 0;
2412 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2413 GL_STENCIL_INDEX8 : 0;
2416 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2419 // If depth is requested at all, use the packed depth stencil format if
2420 // it's available, as some desktop GL drivers don't support any non-packed
2421 // formats for depth attachments.
2422 const bool depth24_stencil8_supported =
2423 feature_info_->feature_flags().packed_depth24_stencil8;
2424 VLOG(1) << "GL_EXT_packed_depth_stencil "
2425 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2427 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2428 depth24_stencil8_supported) {
2429 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2430 offscreen_target_stencil_format_ = 0;
2432 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2433 GL_DEPTH_COMPONENT : 0;
2434 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2435 GL_STENCIL_INDEX : 0;
2439 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2442 // Create the target frame buffer. This is the one that the client renders
2444 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2445 offscreen_target_frame_buffer_->Create();
2446 // Due to GLES2 format limitations, either the color texture (for
2447 // non-multisampling) or the color render buffer (for multisampling) will be
2448 // attached to the offscreen frame buffer. The render buffer has more
2449 // limited formats available to it, but the texture can't do multisampling.
2450 if (IsOffscreenBufferMultisampled()) {
2451 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2452 renderbuffer_manager(), memory_tracker(), &state_));
2453 offscreen_target_color_render_buffer_->Create();
2455 offscreen_target_color_texture_.reset(new BackTexture(
2456 memory_tracker(), &state_));
2457 offscreen_target_color_texture_->Create();
2459 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2460 renderbuffer_manager(), memory_tracker(), &state_));
2461 offscreen_target_depth_render_buffer_->Create();
2462 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2463 renderbuffer_manager(), memory_tracker(), &state_));
2464 offscreen_target_stencil_render_buffer_->Create();
2466 // Create the saved offscreen texture. The target frame buffer is copied
2467 // here when SwapBuffers is called.
2468 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2469 offscreen_saved_frame_buffer_->Create();
2471 offscreen_saved_color_texture_.reset(new BackTexture(
2472 memory_tracker(), &state_));
2473 offscreen_saved_color_texture_->Create();
2475 // Allocate the render buffers at their initial size and check the status
2476 // of the frame buffers is okay.
2477 if (!ResizeOffscreenFrameBuffer(size)) {
2478 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2483 // Allocate the offscreen saved color texture.
2484 DCHECK(offscreen_saved_color_format_);
2485 offscreen_saved_color_texture_->AllocateStorage(
2486 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2488 offscreen_saved_frame_buffer_->AttachRenderTexture(
2489 offscreen_saved_color_texture_.get());
2490 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2491 GL_FRAMEBUFFER_COMPLETE) {
2492 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2497 // Bind to the new default frame buffer (the offscreen target frame buffer).
2498 // This should now be associated with ID zero.
2499 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2501 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2502 // These are NOT if the back buffer has these proprorties. They are
2503 // if we want the command buffer to enforce them regardless of what
2504 // the real backbuffer is assuming the real back buffer gives us more than
2505 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2506 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2507 // can't do anything about that.
2510 glGetIntegerv(GL_ALPHA_BITS, &v);
2511 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2512 // user requested RGB then RGB. If the user did not specify a preference
2513 // than use whatever we were given. Same for DEPTH and STENCIL.
2514 back_buffer_color_format_ =
2515 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2516 glGetIntegerv(GL_DEPTH_BITS, &v);
2517 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2518 glGetIntegerv(GL_STENCIL_BITS, &v);
2519 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2522 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2523 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2524 // isn't well documented; it was discovered in the Khronos OpenGL ES
2525 // mailing list archives. It also implicitly enables the desktop GL
2526 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2527 // variable in fragment shaders.
2528 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2529 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2530 glEnable(GL_POINT_SPRITE);
2533 has_robustness_extension_ =
2534 context->HasExtension("GL_ARB_robustness") ||
2535 context->HasExtension("GL_EXT_robustness");
2537 if (!InitializeShaderTranslator()) {
2541 state_.viewport_width = size.width();
2542 state_.viewport_height = size.height();
2544 GLint viewport_params[4] = { 0 };
2545 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2546 viewport_max_width_ = viewport_params[0];
2547 viewport_max_height_ = viewport_params[1];
2549 state_.scissor_width = state_.viewport_width;
2550 state_.scissor_height = state_.viewport_height;
2552 // Set all the default state because some GL drivers get it wrong.
2553 state_.InitCapabilities();
2555 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2557 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2558 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2559 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2560 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2562 bool call_gl_clear = true;
2563 #if defined(OS_ANDROID)
2564 // Temporary workaround for Android WebView because this clear ignores the
2565 // clip and corrupts that external UI of the App. Not calling glClear is ok
2566 // because the system already clears the buffer before each draw. Proper
2567 // fix might be setting the scissor clip properly before initialize. See
2568 // crbug.com/259023 for details.
2569 call_gl_clear = surface_->GetHandle();
2571 if (call_gl_clear) {
2572 // Clear the backbuffer.
2573 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2576 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2577 if (feature_info_->workarounds()
2578 .disable_post_sub_buffers_for_onscreen_surfaces &&
2579 !surface->IsOffscreen())
2580 supports_post_sub_buffer_ = false;
2582 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2583 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2586 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2587 context_->SetUnbindFboOnMakeCurrent();
2590 if (feature_info_->workarounds().release_image_after_use) {
2591 image_manager()->SetReleaseAfterUse();
2594 // Only compositor contexts are known to use only the subset of GL
2595 // that can be safely migrated between the iGPU and the dGPU. Mark
2596 // those contexts as safe to forcibly transition between the GPUs.
2597 // http://crbug.com/180876, http://crbug.com/227228
2599 context_->SetSafeToForceGpuSwitch();
2601 async_pixel_transfer_manager_.reset(
2602 AsyncPixelTransferManager::Create(context.get()));
2603 async_pixel_transfer_manager_->Initialize(texture_manager());
2605 framebuffer_manager()->AddObserver(this);
2610 Capabilities GLES2DecoderImpl::GetCapabilities() {
2611 DCHECK(initialized());
2615 caps.fast_npot_mo8_textures =
2616 feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
2617 caps.egl_image_external =
2618 feature_info_->feature_flags().oes_egl_image_external;
2619 caps.texture_format_bgra8888 =
2620 feature_info_->feature_flags().ext_texture_format_bgra8888;
2621 caps.texture_format_etc1 =
2622 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2623 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2624 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2625 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2626 caps.discard_framebuffer =
2627 feature_info_->feature_flags().ext_discard_framebuffer;
2629 #if defined(OS_MACOSX)
2630 // This is unconditionally true on mac, no need to test for it at runtime.
2631 caps.iosurface = true;
2634 caps.post_sub_buffer = supports_post_sub_buffer_;
2639 void GLES2DecoderImpl::UpdateCapabilities() {
2640 util_.set_num_compressed_texture_formats(
2641 validators_->compressed_texture_format.GetValues().size());
2642 util_.set_num_shader_binary_formats(
2643 validators_->shader_binary_format.GetValues().size());
2646 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2647 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2649 if (!use_shader_translator_) {
2652 ShBuiltInResources resources;
2653 ShInitBuiltInResources(&resources);
2654 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2655 resources.MaxVertexUniformVectors =
2656 group_->max_vertex_uniform_vectors();
2657 resources.MaxVaryingVectors = group_->max_varying_vectors();
2658 resources.MaxVertexTextureImageUnits =
2659 group_->max_vertex_texture_image_units();
2660 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2661 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2662 resources.MaxFragmentUniformVectors =
2663 group_->max_fragment_uniform_vectors();
2664 resources.MaxDrawBuffers = group_->max_draw_buffers();
2665 resources.MaxExpressionComplexity = 256;
2666 resources.MaxCallStackDepth = 256;
2668 #if (ANGLE_SH_VERSION >= 110)
2669 GLint range[2] = { 0, 0 };
2670 GLint precision = 0;
2671 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2673 resources.FragmentPrecisionHigh =
2674 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2677 if (force_webgl_glsl_validation_) {
2678 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2679 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2680 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2681 if (!draw_buffers_explicitly_enabled_)
2682 resources.MaxDrawBuffers = 1;
2684 resources.OES_standard_derivatives =
2685 features().oes_standard_derivatives ? 1 : 0;
2686 resources.ARB_texture_rectangle =
2687 features().arb_texture_rectangle ? 1 : 0;
2688 resources.OES_EGL_image_external =
2689 features().oes_egl_image_external ? 1 : 0;
2690 resources.EXT_draw_buffers =
2691 features().ext_draw_buffers ? 1 : 0;
2692 resources.EXT_frag_depth =
2693 features().ext_frag_depth ? 1 : 0;
2696 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2698 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2699 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2700 resources.HashFunction = &CityHashForAngle;
2702 resources.HashFunction = &CityHash64;
2705 resources.HashFunction = NULL;
2706 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2707 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2708 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2709 int driver_bug_workarounds = 0;
2710 if (workarounds().needs_glsl_built_in_function_emulation)
2711 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2712 if (workarounds().init_gl_position_in_vertex_shader)
2713 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2714 if (workarounds().unfold_short_circuit_as_ternary_operation)
2715 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2716 if (workarounds().init_varyings_without_static_use)
2717 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2718 if (workarounds().unroll_for_loop_with_sampler_array_index)
2719 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2721 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2722 vertex_translator_ = cache->GetTranslator(
2723 SH_VERTEX_SHADER, shader_spec, &resources,
2724 implementation_type,
2725 static_cast<ShCompileOptions>(driver_bug_workarounds));
2726 if (!vertex_translator_.get()) {
2727 LOG(ERROR) << "Could not initialize vertex shader translator.";
2732 fragment_translator_ = cache->GetTranslator(
2733 SH_FRAGMENT_SHADER, shader_spec, &resources,
2734 implementation_type,
2735 static_cast<ShCompileOptions>(driver_bug_workarounds));
2736 if (!fragment_translator_.get()) {
2737 LOG(ERROR) << "Could not initialize fragment shader translator.";
2744 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2745 for (GLsizei ii = 0; ii < n; ++ii) {
2746 if (GetBuffer(client_ids[ii])) {
2750 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2751 glGenBuffersARB(n, service_ids.get());
2752 for (GLsizei ii = 0; ii < n; ++ii) {
2753 CreateBuffer(client_ids[ii], service_ids[ii]);
2758 bool GLES2DecoderImpl::GenFramebuffersHelper(
2759 GLsizei n, const GLuint* client_ids) {
2760 for (GLsizei ii = 0; ii < n; ++ii) {
2761 if (GetFramebuffer(client_ids[ii])) {
2765 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2766 glGenFramebuffersEXT(n, service_ids.get());
2767 for (GLsizei ii = 0; ii < n; ++ii) {
2768 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2773 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2774 GLsizei n, const GLuint* client_ids) {
2775 for (GLsizei ii = 0; ii < n; ++ii) {
2776 if (GetRenderbuffer(client_ids[ii])) {
2780 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2781 glGenRenderbuffersEXT(n, service_ids.get());
2782 for (GLsizei ii = 0; ii < n; ++ii) {
2783 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2788 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2789 for (GLsizei ii = 0; ii < n; ++ii) {
2790 if (GetTexture(client_ids[ii])) {
2794 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2795 glGenTextures(n, service_ids.get());
2796 for (GLsizei ii = 0; ii < n; ++ii) {
2797 CreateTexture(client_ids[ii], service_ids[ii]);
2802 void GLES2DecoderImpl::DeleteBuffersHelper(
2803 GLsizei n, const GLuint* client_ids) {
2804 for (GLsizei ii = 0; ii < n; ++ii) {
2805 Buffer* buffer = GetBuffer(client_ids[ii]);
2806 if (buffer && !buffer->IsDeleted()) {
2807 state_.vertex_attrib_manager->Unbind(buffer);
2808 if (state_.bound_array_buffer.get() == buffer) {
2809 state_.bound_array_buffer = NULL;
2811 RemoveBuffer(client_ids[ii]);
2816 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2817 GLsizei n, const GLuint* client_ids) {
2818 bool supports_separate_framebuffer_binds =
2819 features().chromium_framebuffer_multisample;
2821 for (GLsizei ii = 0; ii < n; ++ii) {
2822 Framebuffer* framebuffer =
2823 GetFramebuffer(client_ids[ii]);
2824 if (framebuffer && !framebuffer->IsDeleted()) {
2825 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2826 framebuffer_state_.bound_draw_framebuffer = NULL;
2827 framebuffer_state_.clear_state_dirty = true;
2828 GLenum target = supports_separate_framebuffer_binds ?
2829 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2830 glBindFramebufferEXT(target, GetBackbufferServiceId());
2832 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2833 framebuffer_state_.bound_read_framebuffer = NULL;
2834 GLenum target = supports_separate_framebuffer_binds ?
2835 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2836 glBindFramebufferEXT(target, GetBackbufferServiceId());
2839 RemoveFramebuffer(client_ids[ii]);
2844 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2845 GLsizei n, const GLuint* client_ids) {
2846 bool supports_separate_framebuffer_binds =
2847 features().chromium_framebuffer_multisample;
2848 for (GLsizei ii = 0; ii < n; ++ii) {
2849 Renderbuffer* renderbuffer =
2850 GetRenderbuffer(client_ids[ii]);
2851 if (renderbuffer && !renderbuffer->IsDeleted()) {
2852 if (state_.bound_renderbuffer.get() == renderbuffer) {
2853 state_.bound_renderbuffer = NULL;
2855 // Unbind from current framebuffers.
2856 if (supports_separate_framebuffer_binds) {
2857 if (framebuffer_state_.bound_read_framebuffer.get()) {
2858 framebuffer_state_.bound_read_framebuffer
2859 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2861 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2862 framebuffer_state_.bound_draw_framebuffer
2863 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2866 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2867 framebuffer_state_.bound_draw_framebuffer
2868 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2871 framebuffer_state_.clear_state_dirty = true;
2872 RemoveRenderbuffer(client_ids[ii]);
2877 void GLES2DecoderImpl::DeleteTexturesHelper(
2878 GLsizei n, const GLuint* client_ids) {
2879 bool supports_separate_framebuffer_binds =
2880 features().chromium_framebuffer_multisample;
2881 for (GLsizei ii = 0; ii < n; ++ii) {
2882 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2884 Texture* texture = texture_ref->texture();
2885 if (texture->IsAttachedToFramebuffer()) {
2886 framebuffer_state_.clear_state_dirty = true;
2888 // Unbind texture_ref from texture_ref units.
2889 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2890 state_.texture_units[jj].Unbind(texture_ref);
2892 // Unbind from current framebuffers.
2893 if (supports_separate_framebuffer_binds) {
2894 if (framebuffer_state_.bound_read_framebuffer.get()) {
2895 framebuffer_state_.bound_read_framebuffer
2896 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2898 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2899 framebuffer_state_.bound_draw_framebuffer
2900 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2903 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2904 framebuffer_state_.bound_draw_framebuffer
2905 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2908 #if defined(OS_MACOSX)
2909 GLuint service_id = texture->service_id();
2910 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2911 ReleaseIOSurfaceForTexture(service_id);
2914 RemoveTexture(client_ids[ii]);
2919 // } // anonymous namespace
2921 bool GLES2DecoderImpl::MakeCurrent() {
2922 if (!context_.get())
2925 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
2926 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2928 // Some D3D drivers cannot recover from device lost in the GPU process
2929 // sandbox. Allow a new GPU process to launch.
2930 if (workarounds().exit_on_context_lost) {
2931 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2932 << " a D3D device in the Chrome GPU process sandbox.";
2934 base::win::SetShouldCrashOnProcessDetach(false);
2942 ProcessFinishedAsyncTransfers();
2944 // Rebind the FBO if it was unbound by the context.
2945 if (workarounds().unbind_fbo_on_context_switch)
2946 RestoreFramebufferBindings();
2948 framebuffer_state_.clear_state_dirty = true;
2953 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
2954 ProcessPendingReadPixels();
2955 if (engine() && query_manager_.get())
2956 query_manager_->ProcessPendingTransferQueries();
2958 // TODO(epenner): Is there a better place to do this?
2959 // This needs to occur before we execute any batch of commands
2960 // from the client, as the client may have recieved an async
2961 // completion while issuing those commands.
2962 // "DidFlushStart" would be ideal if we had such a callback.
2963 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
2966 static void RebindCurrentFramebuffer(
2968 Framebuffer* framebuffer,
2969 GLuint back_buffer_service_id) {
2970 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
2972 if (framebuffer_id == 0) {
2973 framebuffer_id = back_buffer_service_id;
2976 glBindFramebufferEXT(target, framebuffer_id);
2979 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
2980 framebuffer_state_.clear_state_dirty = true;
2982 if (!features().chromium_framebuffer_multisample) {
2983 RebindCurrentFramebuffer(
2985 framebuffer_state_.bound_draw_framebuffer.get(),
2986 GetBackbufferServiceId());
2988 RebindCurrentFramebuffer(
2989 GL_READ_FRAMEBUFFER_EXT,
2990 framebuffer_state_.bound_read_framebuffer.get(),
2991 GetBackbufferServiceId());
2992 RebindCurrentFramebuffer(
2993 GL_DRAW_FRAMEBUFFER_EXT,
2994 framebuffer_state_.bound_draw_framebuffer.get(),
2995 GetBackbufferServiceId());
3000 bool GLES2DecoderImpl::CheckFramebufferValid(
3001 Framebuffer* framebuffer,
3002 GLenum target, const char* func_name) {
3004 if (backbuffer_needs_clear_bits_) {
3005 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3006 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3007 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3012 glDisable(GL_SCISSOR_TEST);
3013 glClear(backbuffer_needs_clear_bits_);
3014 backbuffer_needs_clear_bits_ = 0;
3015 RestoreClearState();
3020 if (framebuffer_manager()->IsComplete(framebuffer)) {
3024 GLenum completeness = framebuffer->IsPossiblyComplete();
3025 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3027 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3031 // Are all the attachments cleared?
3032 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3033 texture_manager()->HaveUnclearedMips()) {
3034 if (!framebuffer->IsCleared()) {
3035 // Can we clear them?
3036 if (framebuffer->GetStatus(texture_manager(), target) !=
3037 GL_FRAMEBUFFER_COMPLETE) {
3039 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3040 "framebuffer incomplete (clear)");
3043 ClearUnclearedAttachments(target, framebuffer);
3047 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3048 if (framebuffer->GetStatus(texture_manager(), target) !=
3049 GL_FRAMEBUFFER_COMPLETE) {
3051 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3052 "framebuffer incomplete (check)");
3055 framebuffer_manager()->MarkAsComplete(framebuffer);
3058 // NOTE: At this point we don't know if the framebuffer is complete but
3059 // we DO know that everything that needs to be cleared has been cleared.
3063 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3064 if (!features().chromium_framebuffer_multisample) {
3065 bool valid = CheckFramebufferValid(
3066 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3074 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3075 GL_DRAW_FRAMEBUFFER_EXT,
3077 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3078 GL_READ_FRAMEBUFFER_EXT,
3082 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3083 Framebuffer* framebuffer =
3084 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3085 if (framebuffer != NULL) {
3086 const Framebuffer::Attachment* attachment =
3087 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3089 return gfx::Size(attachment->width(), attachment->height());
3091 return gfx::Size(0, 0);
3092 } else if (offscreen_target_frame_buffer_.get()) {
3093 return offscreen_size_;
3095 return surface_->GetSize();
3099 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3100 Framebuffer* framebuffer =
3101 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3102 if (framebuffer != NULL) {
3103 return framebuffer->GetColorAttachmentTextureType();
3105 return GL_UNSIGNED_BYTE;
3109 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3110 Framebuffer* framebuffer =
3111 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3112 if (framebuffer != NULL) {
3113 return framebuffer->GetColorAttachmentFormat();
3114 } else if (offscreen_target_frame_buffer_.get()) {
3115 return offscreen_target_color_format_;
3117 return back_buffer_color_format_;
3121 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3122 Framebuffer* framebuffer =
3123 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3124 if (framebuffer != NULL) {
3125 return framebuffer->GetColorAttachmentFormat();
3126 } else if (offscreen_target_frame_buffer_.get()) {
3127 return offscreen_target_color_format_;
3129 return back_buffer_color_format_;
3133 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3134 if (!offscreen_saved_color_texture_info_.get())
3136 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3137 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3138 texture_manager()->SetLevelInfo(
3139 offscreen_saved_color_texture_info_.get(),
3143 offscreen_size_.width(),
3144 offscreen_size_.height(),
3150 texture_manager()->SetParameteri(
3151 "UpdateParentTextureInfo",
3153 offscreen_saved_color_texture_info_.get(),
3154 GL_TEXTURE_MAG_FILTER,
3156 texture_manager()->SetParameteri(
3157 "UpdateParentTextureInfo",
3159 offscreen_saved_color_texture_info_.get(),
3160 GL_TEXTURE_MIN_FILTER,
3162 texture_manager()->SetParameteri(
3163 "UpdateParentTextureInfo",
3165 offscreen_saved_color_texture_info_.get(),
3168 texture_manager()->SetParameteri(
3169 "UpdateParentTextureInfo",
3171 offscreen_saved_color_texture_info_.get(),
3174 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3176 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3179 void GLES2DecoderImpl::SetResizeCallback(
3180 const base::Callback<void(gfx::Size, float)>& callback) {
3181 resize_callback_ = callback;
3184 Logger* GLES2DecoderImpl::GetLogger() {
3188 void GLES2DecoderImpl::BeginDecoding() {
3189 gpu_tracer_->BeginDecoding();
3190 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3193 void GLES2DecoderImpl::EndDecoding() {
3194 gpu_tracer_->EndDecoding();
3197 ErrorState* GLES2DecoderImpl::GetErrorState() {
3198 return state_.GetErrorState();
3201 void GLES2DecoderImpl::SetShaderCacheCallback(
3202 const ShaderCacheCallback& callback) {
3203 shader_cache_callback_ = callback;
3206 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3207 const WaitSyncPointCallback& callback) {
3208 wait_sync_point_callback_ = callback;
3211 AsyncPixelTransferManager*
3212 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3213 return async_pixel_transfer_manager_.get();
3216 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3217 async_pixel_transfer_manager_.reset();
3220 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3221 AsyncPixelTransferManager* manager) {
3222 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3225 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3226 uint32* service_texture_id) {
3227 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3229 *service_texture_id = texture_ref->service_id();
3235 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3236 return texture_state_.texture_upload_count +
3237 async_pixel_transfer_manager_->GetTextureUploadCount();
3240 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3241 return texture_state_.total_texture_upload_time +
3242 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3245 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3246 return total_processing_commands_time_;
3249 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3250 total_processing_commands_time_ += time;
3253 void GLES2DecoderImpl::Destroy(bool have_context) {
3257 DCHECK(!have_context || context_->IsCurrent(NULL));
3259 // Unbind everything.
3260 state_.vertex_attrib_manager = NULL;
3261 default_vertex_attrib_manager_ = NULL;
3262 state_.texture_units.clear();
3263 state_.bound_array_buffer = NULL;
3264 state_.current_queries.clear();
3265 framebuffer_state_.bound_read_framebuffer = NULL;
3266 framebuffer_state_.bound_draw_framebuffer = NULL;
3267 state_.bound_renderbuffer = NULL;
3269 if (offscreen_saved_color_texture_info_.get()) {
3270 DCHECK(offscreen_target_color_texture_);
3271 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3272 offscreen_saved_color_texture_->id());
3273 offscreen_saved_color_texture_->Invalidate();
3274 offscreen_saved_color_texture_info_ = NULL;
3277 if (copy_texture_CHROMIUM_.get()) {
3278 copy_texture_CHROMIUM_->Destroy();
3279 copy_texture_CHROMIUM_.reset();
3282 if (state_.current_program.get()) {
3283 program_manager()->UnuseProgram(shader_manager(),
3284 state_.current_program.get());
3287 if (attrib_0_buffer_id_) {
3288 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3290 if (fixed_attrib_buffer_id_) {
3291 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3294 if (validation_texture_) {
3295 glDeleteTextures(1, &validation_texture_);
3296 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3297 glDeleteFramebuffersEXT(1, &validation_fbo_);
3300 if (offscreen_target_frame_buffer_.get())
3301 offscreen_target_frame_buffer_->Destroy();
3302 if (offscreen_target_color_texture_.get())
3303 offscreen_target_color_texture_->Destroy();
3304 if (offscreen_target_color_render_buffer_.get())
3305 offscreen_target_color_render_buffer_->Destroy();
3306 if (offscreen_target_depth_render_buffer_.get())
3307 offscreen_target_depth_render_buffer_->Destroy();
3308 if (offscreen_target_stencil_render_buffer_.get())
3309 offscreen_target_stencil_render_buffer_->Destroy();
3310 if (offscreen_saved_frame_buffer_.get())
3311 offscreen_saved_frame_buffer_->Destroy();
3312 if (offscreen_saved_color_texture_.get())
3313 offscreen_saved_color_texture_->Destroy();
3314 if (offscreen_resolved_frame_buffer_.get())
3315 offscreen_resolved_frame_buffer_->Destroy();
3316 if (offscreen_resolved_color_texture_.get())
3317 offscreen_resolved_color_texture_->Destroy();
3319 if (offscreen_target_frame_buffer_.get())
3320 offscreen_target_frame_buffer_->Invalidate();
3321 if (offscreen_target_color_texture_.get())
3322 offscreen_target_color_texture_->Invalidate();
3323 if (offscreen_target_color_render_buffer_.get())
3324 offscreen_target_color_render_buffer_->Invalidate();
3325 if (offscreen_target_depth_render_buffer_.get())
3326 offscreen_target_depth_render_buffer_->Invalidate();
3327 if (offscreen_target_stencil_render_buffer_.get())
3328 offscreen_target_stencil_render_buffer_->Invalidate();
3329 if (offscreen_saved_frame_buffer_.get())
3330 offscreen_saved_frame_buffer_->Invalidate();
3331 if (offscreen_saved_color_texture_.get())
3332 offscreen_saved_color_texture_->Invalidate();
3333 if (offscreen_resolved_frame_buffer_.get())
3334 offscreen_resolved_frame_buffer_->Invalidate();
3335 if (offscreen_resolved_color_texture_.get())
3336 offscreen_resolved_color_texture_->Invalidate();
3339 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3340 // Otherwise, we can leak objects. http://crbug.com/258772.
3341 // state_.current_program must be reset before group_ is reset because
3342 // the later deletes the ProgramManager object that referred by
3343 // state_.current_program object.
3344 state_.current_program = NULL;
3346 copy_texture_CHROMIUM_.reset();
3348 if (query_manager_.get()) {
3349 query_manager_->Destroy(have_context);
3350 query_manager_.reset();
3353 if (vertex_array_manager_ .get()) {
3354 vertex_array_manager_->Destroy(have_context);
3355 vertex_array_manager_.reset();
3358 offscreen_target_frame_buffer_.reset();
3359 offscreen_target_color_texture_.reset();
3360 offscreen_target_color_render_buffer_.reset();
3361 offscreen_target_depth_render_buffer_.reset();
3362 offscreen_target_stencil_render_buffer_.reset();
3363 offscreen_saved_frame_buffer_.reset();
3364 offscreen_saved_color_texture_.reset();
3365 offscreen_resolved_frame_buffer_.reset();
3366 offscreen_resolved_color_texture_.reset();
3368 // Should destroy the transfer manager before the texture manager held
3369 // by the context group.
3370 async_pixel_transfer_manager_.reset();
3373 framebuffer_manager()->RemoveObserver(this);
3374 group_->Destroy(this, have_context);
3378 if (context_.get()) {
3379 context_->ReleaseCurrent(NULL);
3383 #if defined(OS_MACOSX)
3384 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3385 it != texture_to_io_surface_map_.end(); ++it) {
3386 CFRelease(it->second);
3388 texture_to_io_surface_map_.clear();
3392 void GLES2DecoderImpl::SetSurface(
3393 const scoped_refptr<gfx::GLSurface>& surface) {
3394 DCHECK(context_->IsCurrent(NULL));
3395 DCHECK(surface_.get());
3397 RestoreCurrentFramebufferBindings();
3400 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3401 if (!offscreen_saved_color_texture_.get()) {
3402 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3405 if (!offscreen_saved_color_texture_info_.get()) {
3406 GLuint service_id = offscreen_saved_color_texture_->id();
3407 offscreen_saved_color_texture_info_ = TextureRef::Create(
3408 texture_manager(), 0, service_id);
3409 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3411 UpdateParentTextureInfo();
3413 mailbox_manager()->ProduceTexture(
3414 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3417 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3418 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3419 if (!is_offscreen) {
3420 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3421 << " with an onscreen framebuffer.";
3425 if (offscreen_size_ == size)
3428 offscreen_size_ = size;
3429 int w = offscreen_size_.width();
3430 int h = offscreen_size_.height();
3431 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3432 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3433 << "to allocate storage due to excessive dimensions.";
3437 // Reallocate the offscreen target buffers.
3438 DCHECK(offscreen_target_color_format_);
3439 if (IsOffscreenBufferMultisampled()) {
3440 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3441 feature_info_, offscreen_size_, offscreen_target_color_format_,
3442 offscreen_target_samples_)) {
3443 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3444 << "to allocate storage for offscreen target color buffer.";
3448 if (!offscreen_target_color_texture_->AllocateStorage(
3449 offscreen_size_, offscreen_target_color_format_, false)) {
3450 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3451 << "to allocate storage for offscreen target color texture.";
3455 if (offscreen_target_depth_format_ &&
3456 !offscreen_target_depth_render_buffer_->AllocateStorage(
3457 feature_info_, offscreen_size_, offscreen_target_depth_format_,
3458 offscreen_target_samples_)) {
3459 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3460 << "to allocate storage for offscreen target depth buffer.";
3463 if (offscreen_target_stencil_format_ &&
3464 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3465 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
3466 offscreen_target_samples_)) {
3467 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3468 << "to allocate storage for offscreen target stencil buffer.";
3472 // Attach the offscreen target buffers to the target frame buffer.
3473 if (IsOffscreenBufferMultisampled()) {
3474 offscreen_target_frame_buffer_->AttachRenderBuffer(
3475 GL_COLOR_ATTACHMENT0,
3476 offscreen_target_color_render_buffer_.get());
3478 offscreen_target_frame_buffer_->AttachRenderTexture(
3479 offscreen_target_color_texture_.get());
3481 if (offscreen_target_depth_format_) {
3482 offscreen_target_frame_buffer_->AttachRenderBuffer(
3483 GL_DEPTH_ATTACHMENT,
3484 offscreen_target_depth_render_buffer_.get());
3486 const bool packed_depth_stencil =
3487 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3488 if (packed_depth_stencil) {
3489 offscreen_target_frame_buffer_->AttachRenderBuffer(
3490 GL_STENCIL_ATTACHMENT,
3491 offscreen_target_depth_render_buffer_.get());
3492 } else if (offscreen_target_stencil_format_) {
3493 offscreen_target_frame_buffer_->AttachRenderBuffer(
3494 GL_STENCIL_ATTACHMENT,
3495 offscreen_target_stencil_render_buffer_.get());
3498 if (offscreen_target_frame_buffer_->CheckStatus() !=
3499 GL_FRAMEBUFFER_COMPLETE) {
3500 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3501 << "because offscreen FBO was incomplete.";
3505 // Clear the target frame buffer.
3507 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3508 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3509 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3510 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3512 glStencilMaskSeparate(GL_FRONT, -1);
3513 glStencilMaskSeparate(GL_BACK, -1);
3515 glDepthMask(GL_TRUE);
3516 glDisable(GL_SCISSOR_TEST);
3517 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3518 RestoreClearState();
3521 // Destroy the offscreen resolved framebuffers.
3522 if (offscreen_resolved_frame_buffer_.get())
3523 offscreen_resolved_frame_buffer_->Destroy();
3524 if (offscreen_resolved_color_texture_.get())
3525 offscreen_resolved_color_texture_->Destroy();
3526 offscreen_resolved_color_texture_.reset();
3527 offscreen_resolved_frame_buffer_.reset();
3532 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3533 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3534 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3535 return error::kDeferCommandUntilLater;
3537 GLuint width = static_cast<GLuint>(c.width);
3538 GLuint height = static_cast<GLuint>(c.height);
3539 GLfloat scale_factor = c.scale_factor;
3540 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3542 width = std::max(1U, width);
3543 height = std::max(1U, height);
3545 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3546 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3547 // Make sure that we are done drawing to the back buffer before resizing.
3550 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3552 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3553 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3554 << "ResizeOffscreenFrameBuffer failed.";
3555 return error::kLostContext;
3559 if (!resize_callback_.is_null()) {
3560 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3561 DCHECK(context_->IsCurrent(surface_.get()));
3562 if (!context_->IsCurrent(surface_.get())) {
3563 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3564 << "current after resize callback.";
3565 return error::kLostContext;
3569 return error::kNoError;
3572 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3573 if (command_id > kStartPoint && command_id < kNumCommands) {
3574 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3576 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3579 // Decode command with its arguments, and call the corresponding GL function.
3580 // Note: args is a pointer to the command buffer. As such, it could be changed
3581 // by a (malicious) client at any time, so if validation has to happen, it
3582 // should operate on a copy of them.
3583 error::Error GLES2DecoderImpl::DoCommand(
3584 unsigned int command,
3585 unsigned int arg_count,
3586 const void* cmd_data) {
3587 error::Error result = error::kNoError;
3588 if (log_commands()) {
3589 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3590 // VLOG(1), no luck.
3591 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3592 << GetCommandName(command);
3594 unsigned int command_index = command - kStartPoint - 1;
3595 if (command_index < arraysize(g_command_info)) {
3596 const CommandInfo& info = g_command_info[command_index];
3597 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3598 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3599 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3600 bool doing_gpu_trace = false;
3601 if (gpu_trace_commands_) {
3602 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3603 doing_gpu_trace = true;
3604 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3608 uint32 immediate_data_size =
3609 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3611 #define GLES2_CMD_OP(name) \
3612 case cmds::name::kCmdId: \
3613 result = Handle ## name( \
3614 immediate_data_size, \
3615 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3618 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3622 if (doing_gpu_trace)
3623 gpu_tracer_->End(kTraceDecoder);
3627 while ((error = glGetError()) != GL_NO_ERROR) {
3628 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3629 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3630 << GetCommandName(command);
3631 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3635 result = error::kInvalidArguments;
3638 result = DoCommonCommand(command, arg_count, cmd_data);
3640 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3641 result = current_decoder_error_;
3642 current_decoder_error_ = error::kNoError;
3647 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3648 buffer_manager()->RemoveBuffer(client_id);
3651 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3652 if (GetProgram(client_id)) {
3655 GLuint service_id = glCreateProgram();
3656 if (service_id != 0) {
3657 CreateProgram(client_id, service_id);
3662 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3663 if (GetShader(client_id)) {
3666 GLuint service_id = glCreateShader(type);
3667 if (service_id != 0) {
3668 CreateShader(client_id, service_id, type);
3673 void GLES2DecoderImpl::DoFinish() {
3675 ProcessPendingReadPixels();
3676 ProcessPendingQueries();
3679 void GLES2DecoderImpl::DoFlush() {
3681 ProcessPendingQueries();
3684 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3685 GLuint texture_index = texture_unit - GL_TEXTURE0;
3686 if (texture_index >= state_.texture_units.size()) {
3687 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3688 "glActiveTexture", texture_unit, "texture_unit");
3691 state_.active_texture_unit = texture_index;
3692 glActiveTexture(texture_unit);
3695 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3696 Buffer* buffer = NULL;
3697 GLuint service_id = 0;
3698 if (client_id != 0) {
3699 buffer = GetBuffer(client_id);
3701 if (!group_->bind_generates_resource()) {
3702 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3704 "id not generated by glGenBuffers");
3708 // It's a new id so make a buffer buffer for it.
3709 glGenBuffersARB(1, &service_id);
3710 CreateBuffer(client_id, service_id);
3711 buffer = GetBuffer(client_id);
3712 IdAllocatorInterface* id_allocator =
3713 group_->GetIdAllocator(id_namespaces::kBuffers);
3714 id_allocator->MarkAsUsed(client_id);
3717 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3719 if (!buffer_manager()->SetTarget(buffer, target)) {
3721 GL_INVALID_OPERATION,
3722 "glBindBuffer", "buffer bound to more than 1 target");
3725 service_id = buffer->service_id();
3728 case GL_ARRAY_BUFFER:
3729 state_.bound_array_buffer = buffer;
3731 case GL_ELEMENT_ARRAY_BUFFER:
3732 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3735 NOTREACHED(); // Validation should prevent us getting here.
3738 glBindBuffer(target, service_id);
3741 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3742 bool all_draw_buffers) {
3743 Framebuffer* framebuffer =
3744 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3745 if (!all_draw_buffers || !framebuffer) {
3746 return (GLES2Util::GetChannelsForFormat(
3747 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3749 return framebuffer->HasAlphaMRT();
3752 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3753 Framebuffer* framebuffer =
3754 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3756 return framebuffer->HasDepthAttachment();
3758 if (offscreen_target_frame_buffer_.get()) {
3759 return offscreen_target_depth_format_ != 0;
3761 return back_buffer_has_depth_;
3764 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3765 Framebuffer* framebuffer =
3766 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3768 return framebuffer->HasStencilAttachment();
3770 if (offscreen_target_frame_buffer_.get()) {
3771 return offscreen_target_stencil_format_ != 0 ||
3772 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3774 return back_buffer_has_stencil_;
3777 void GLES2DecoderImpl::ApplyDirtyState() {
3778 if (framebuffer_state_.clear_state_dirty) {
3780 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3781 state_.color_mask_alpha &&
3782 BoundFramebufferHasColorAttachmentWithAlpha(true));
3783 bool have_depth = BoundFramebufferHasDepthAttachment();
3784 glDepthMask(state_.depth_mask && have_depth);
3785 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3786 bool have_stencil = BoundFramebufferHasStencilAttachment();
3787 glStencilMaskSeparate(
3788 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3789 glStencilMaskSeparate(
3790 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3792 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3793 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3794 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3795 EnableDisable(GL_BLEND, state_.enable_flags.blend);
3796 framebuffer_state_.clear_state_dirty = false;
3800 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3801 return (offscreen_target_frame_buffer_.get())
3802 ? offscreen_target_frame_buffer_->id()
3803 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3806 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) const {
3807 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3808 "context", logger_.GetLogPrefix());
3809 // Restore the Framebuffer first because of bugs in Intel drivers.
3810 // Intel drivers incorrectly clip the viewport settings to
3811 // the size of the current framebuffer object.
3812 RestoreFramebufferBindings();
3813 state_.RestoreState(prev_state);
3816 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3818 framebuffer_state_.bound_draw_framebuffer.get()
3819 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3820 : GetBackbufferServiceId();
3821 if (!features().chromium_framebuffer_multisample) {
3822 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3824 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3825 service_id = framebuffer_state_.bound_read_framebuffer.get()
3826 ? framebuffer_state_.bound_read_framebuffer->service_id()
3827 : GetBackbufferServiceId();
3828 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3833 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3834 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3836 GLenum target = texture->target();
3837 glBindTexture(target, service_id);
3839 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3841 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3843 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3845 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3846 RestoreTextureUnitBindings(state_.active_texture_unit);
3850 void GLES2DecoderImpl::ClearAllAttributes() const {
3851 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
3852 if (i != 0) // Never disable attribute 0
3853 glDisableVertexAttribArray(i);
3854 if(features().angle_instanced_arrays)
3855 glVertexAttribDivisorANGLE(i, 0);
3859 void GLES2DecoderImpl::RestoreAllAttributes() const {
3860 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i)
3861 RestoreAttribute(i);
3864 void GLES2DecoderImpl::OnFboChanged() const {
3865 if (workarounds().restore_scissor_on_fbo_change)
3866 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3869 // Called after the FBO is checked for completeness.
3870 void GLES2DecoderImpl::OnUseFramebuffer() const {
3871 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3872 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3873 // The driver forgets the correct scissor when modifying the FBO binding.
3874 glScissor(state_.scissor_x,
3876 state_.scissor_width,
3877 state_.scissor_height);
3879 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3880 // it's unclear how this bug works.
3885 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3886 Framebuffer* framebuffer = NULL;
3887 GLuint service_id = 0;
3888 if (client_id != 0) {
3889 framebuffer = GetFramebuffer(client_id);
3891 if (!group_->bind_generates_resource()) {
3892 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3893 "glBindFramebuffer",
3894 "id not generated by glGenFramebuffers");
3898 // It's a new id so make a framebuffer framebuffer for it.
3899 glGenFramebuffersEXT(1, &service_id);
3900 CreateFramebuffer(client_id, service_id);
3901 framebuffer = GetFramebuffer(client_id);
3902 IdAllocatorInterface* id_allocator =
3903 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3904 id_allocator->MarkAsUsed(client_id);
3906 service_id = framebuffer->service_id();
3908 framebuffer->MarkAsValid();
3910 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
3912 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3913 framebuffer_state_.bound_draw_framebuffer = framebuffer;
3916 // vmiura: This looks like dup code
3917 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3918 framebuffer_state_.bound_read_framebuffer = framebuffer;
3921 framebuffer_state_.clear_state_dirty = true;
3923 // If we are rendering to the backbuffer get the FBO id for any simulated
3925 if (framebuffer == NULL) {
3926 service_id = GetBackbufferServiceId();
3929 glBindFramebufferEXT(target, service_id);
3933 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3934 Renderbuffer* renderbuffer = NULL;
3935 GLuint service_id = 0;
3936 if (client_id != 0) {
3937 renderbuffer = GetRenderbuffer(client_id);
3938 if (!renderbuffer) {
3939 if (!group_->bind_generates_resource()) {
3940 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3941 "glBindRenderbuffer",
3942 "id not generated by glGenRenderbuffers");
3946 // It's a new id so make a renderbuffer renderbuffer for it.
3947 glGenRenderbuffersEXT(1, &service_id);
3948 CreateRenderbuffer(client_id, service_id);
3949 renderbuffer = GetRenderbuffer(client_id);
3950 IdAllocatorInterface* id_allocator =
3951 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3952 id_allocator->MarkAsUsed(client_id);
3954 service_id = renderbuffer->service_id();
3956 renderbuffer->MarkAsValid();
3958 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
3959 state_.bound_renderbuffer = renderbuffer;
3960 glBindRenderbufferEXT(target, service_id);
3963 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
3964 TextureRef* texture_ref = NULL;
3965 GLuint service_id = 0;
3966 if (client_id != 0) {
3967 texture_ref = GetTexture(client_id);
3969 if (!group_->bind_generates_resource()) {
3970 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3972 "id not generated by glGenTextures");
3976 // It's a new id so make a texture texture for it.
3977 glGenTextures(1, &service_id);
3978 DCHECK_NE(0u, service_id);
3979 CreateTexture(client_id, service_id);
3980 texture_ref = GetTexture(client_id);
3981 IdAllocatorInterface* id_allocator =
3982 group_->GetIdAllocator(id_namespaces::kTextures);
3983 id_allocator->MarkAsUsed(client_id);
3986 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
3988 Texture* texture = texture_ref->texture();
3990 // Check the texture exists
3991 // Check that we are not trying to bind it to a different target.
3992 if (texture->target() != 0 && texture->target() != target) {
3994 GL_INVALID_OPERATION,
3995 "glBindTexture", "texture bound to more than 1 target.");
3998 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3999 if (texture->target() == 0) {
4000 texture_manager()->SetTarget(texture_ref, target);
4002 glBindTexture(target, texture->service_id());
4004 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4005 unit.bind_target = target;
4008 unit.bound_texture_2d = texture_ref;
4010 case GL_TEXTURE_CUBE_MAP:
4011 unit.bound_texture_cube_map = texture_ref;
4013 case GL_TEXTURE_EXTERNAL_OES:
4014 unit.bound_texture_external_oes = texture_ref;
4016 case GL_TEXTURE_RECTANGLE_ARB:
4017 unit.bound_texture_rectangle_arb = texture_ref;
4020 NOTREACHED(); // Validation should prevent us getting here.
4025 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4026 if (state_.vertex_attrib_manager->Enable(index, false)) {
4028 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4029 glDisableVertexAttribArray(index);
4034 "glDisableVertexAttribArray", "index out of range");
4038 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4039 GLsizei numAttachments,
4040 const GLenum* attachments) {
4041 if (!features().ext_discard_framebuffer) {
4042 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4043 "glDiscardFramebufferEXT",
4044 "function not available");
4048 Framebuffer* framebuffer =
4049 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4051 // Validates the attachments. If one of them fails
4052 // the whole command fails.
4053 for (GLsizei i = 0; i < numAttachments; ++i) {
4055 !validators_->attachment.IsValid(attachments[i])) ||
4057 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4058 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4059 "glDiscardFramebufferEXT", attachments[i], "attachments");
4064 // Marks each one of them as not cleared
4065 for (GLsizei i = 0; i < numAttachments; ++i) {
4067 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4072 switch (attachments[i]) {
4074 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4077 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4078 case GL_STENCIL_EXT:
4079 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4088 // If the default framebuffer is bound but we are still rendering to an
4089 // FBO, translate attachment names that refer to default framebuffer
4090 // channels to corresponding framebuffer attachments.
4091 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4092 for (GLsizei i = 0; i < numAttachments; ++i) {
4093 GLenum attachment = attachments[i];
4094 if (!framebuffer && GetBackbufferServiceId()) {
4095 switch (attachment) {
4097 attachment = GL_COLOR_ATTACHMENT0;
4100 attachment = GL_DEPTH_ATTACHMENT;
4102 case GL_STENCIL_EXT:
4103 attachment = GL_STENCIL_ATTACHMENT;
4110 translated_attachments[i] = attachment;
4113 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4116 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4117 if (state_.vertex_attrib_manager->Enable(index, true)) {
4118 glEnableVertexAttribArray(index);
4121 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4125 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4126 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4129 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4131 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4135 if (target == GL_TEXTURE_CUBE_MAP) {
4136 for (int i = 0; i < 6; ++i) {
4137 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4138 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4140 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4145 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4147 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4152 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4153 // Workaround for Mac driver bug. In the large scheme of things setting
4154 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4155 // hit so there's probably no need to make this conditional. The bug appears
4156 // to be that if the filtering mode is set to something that doesn't require
4157 // mipmaps for rendering, or is never set to something other than the default,
4158 // then glGenerateMipmap misbehaves.
4159 if (workarounds().set_texture_filter_before_generating_mipmap) {
4160 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4162 glGenerateMipmapEXT(target);
4163 if (workarounds().set_texture_filter_before_generating_mipmap) {
4164 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4165 texture_ref->texture()->min_filter());
4167 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4168 if (error == GL_NO_ERROR) {
4169 texture_manager()->MarkMipmapsGenerated(texture_ref);
4173 bool GLES2DecoderImpl::GetHelper(
4174 GLenum pname, GLint* params, GLsizei* num_written) {
4175 DCHECK(num_written);
4176 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4178 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4180 // Return the GL implementation's preferred format and (see below type)
4181 // if we have the GL extension that exposes this. This allows the GPU
4182 // client to use the implementation's preferred format for glReadPixels
4183 // for optimisation.
4185 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4186 // case when requested on integer/floating point buffers but which is
4187 // acceptable on GLES2 and with the GL_OES_read_format extension.
4189 // Therefore if an error occurs we swallow the error and use the
4190 // internal implementation.
4192 if (context_->HasExtension("GL_OES_read_format")) {
4193 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4195 glGetIntegerv(pname, params);
4196 if (glGetError() == GL_NO_ERROR)
4199 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4200 GetBoundReadFrameBufferInternalFormat());
4203 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4206 if (context_->HasExtension("GL_OES_read_format")) {
4207 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4209 glGetIntegerv(pname, params);
4210 if (glGetError() == GL_NO_ERROR)
4213 *params = GLES2Util::GetPreferredGLReadPixelsType(
4214 GetBoundReadFrameBufferInternalFormat(),
4215 GetBoundReadFrameBufferTextureType());
4218 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4221 *params = group_->max_fragment_uniform_vectors();
4224 case GL_MAX_VARYING_VECTORS:
4227 *params = group_->max_varying_vectors();
4230 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4233 *params = group_->max_vertex_uniform_vectors();
4239 case GL_MAX_VIEWPORT_DIMS:
4240 if (offscreen_target_frame_buffer_.get()) {
4243 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4244 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4249 case GL_MAX_SAMPLES:
4252 params[0] = renderbuffer_manager()->max_samples();
4255 case GL_MAX_RENDERBUFFER_SIZE:
4258 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4261 case GL_MAX_TEXTURE_SIZE:
4264 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4267 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4270 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4273 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4276 params[0] = group_->max_color_attachments();
4279 case GL_MAX_DRAW_BUFFERS_ARB:
4282 params[0] = group_->max_draw_buffers();
4289 glGetIntegerv(GL_ALPHA_BITS, &v);
4290 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4297 glGetIntegerv(GL_DEPTH_BITS, &v);
4298 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4301 case GL_STENCIL_BITS:
4305 glGetIntegerv(GL_STENCIL_BITS, &v);
4306 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4309 case GL_COMPRESSED_TEXTURE_FORMATS:
4310 *num_written = validators_->compressed_texture_format.GetValues().size();
4312 for (GLint ii = 0; ii < *num_written; ++ii) {
4313 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4317 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4320 *params = validators_->compressed_texture_format.GetValues().size();
4323 case GL_NUM_SHADER_BINARY_FORMATS:
4326 *params = validators_->shader_binary_format.GetValues().size();
4329 case GL_SHADER_BINARY_FORMATS:
4330 *num_written = validators_->shader_binary_format.GetValues().size();
4332 for (GLint ii = 0; ii < *num_written; ++ii) {
4333 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4337 case GL_SHADER_COMPILER:
4343 case GL_ARRAY_BUFFER_BINDING:
4346 if (state_.bound_array_buffer.get()) {
4347 GLuint client_id = 0;
4348 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4350 *params = client_id;
4356 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4359 if (state_.vertex_attrib_manager->element_array_buffer()) {
4360 GLuint client_id = 0;
4361 buffer_manager()->GetClientId(
4362 state_.vertex_attrib_manager->element_array_buffer()->
4363 service_id(), &client_id);
4364 *params = client_id;
4370 case GL_FRAMEBUFFER_BINDING:
4371 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4374 Framebuffer* framebuffer =
4375 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4377 GLuint client_id = 0;
4378 framebuffer_manager()->GetClientId(
4379 framebuffer->service_id(), &client_id);
4380 *params = client_id;
4386 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4389 Framebuffer* framebuffer =
4390 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4392 GLuint client_id = 0;
4393 framebuffer_manager()->GetClientId(
4394 framebuffer->service_id(), &client_id);
4395 *params = client_id;
4401 case GL_RENDERBUFFER_BINDING:
4404 Renderbuffer* renderbuffer =
4405 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4407 *params = renderbuffer->client_id();
4413 case GL_CURRENT_PROGRAM:
4416 if (state_.current_program.get()) {
4417 GLuint client_id = 0;
4418 program_manager()->GetClientId(
4419 state_.current_program->service_id(), &client_id);
4420 *params = client_id;
4426 case GL_VERTEX_ARRAY_BINDING_OES:
4429 if (state_.vertex_attrib_manager.get() !=
4430 default_vertex_attrib_manager_.get()) {
4431 GLuint client_id = 0;
4432 vertex_array_manager_->GetClientId(
4433 state_.vertex_attrib_manager->service_id(), &client_id);
4434 *params = client_id;
4440 case GL_TEXTURE_BINDING_2D:
4443 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4444 if (unit.bound_texture_2d.get()) {
4445 *params = unit.bound_texture_2d->client_id();
4451 case GL_TEXTURE_BINDING_CUBE_MAP:
4454 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4455 if (unit.bound_texture_cube_map.get()) {
4456 *params = unit.bound_texture_cube_map->client_id();
4462 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4465 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4466 if (unit.bound_texture_external_oes.get()) {
4467 *params = unit.bound_texture_external_oes->client_id();
4473 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4476 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4477 if (unit.bound_texture_rectangle_arb.get()) {
4478 *params = unit.bound_texture_rectangle_arb->client_id();
4484 case GL_UNPACK_FLIP_Y_CHROMIUM:
4487 params[0] = unpack_flip_y_;
4490 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4493 params[0] = unpack_premultiply_alpha_;
4496 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4499 params[0] = unpack_unpremultiply_alpha_;
4503 if (pname >= GL_DRAW_BUFFER0_ARB &&
4504 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4507 Framebuffer* framebuffer =
4508 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4510 params[0] = framebuffer->GetDrawBuffer(pname);
4511 } else { // backbuffer
4512 if (pname == GL_DRAW_BUFFER0_ARB)
4513 params[0] = group_->draw_buffer();
4515 params[0] = GL_NONE;
4520 *num_written = util_.GLGetNumValuesReturned(pname);
4525 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4526 GLenum pname, GLsizei* num_values) {
4527 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4530 return GetHelper(pname, NULL, num_values);
4533 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4534 if (GL_MAX_SAMPLES == pname &&
4535 features().use_img_for_multisampled_render_to_texture) {
4536 return GL_MAX_SAMPLES_IMG;
4541 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4543 GLsizei num_written = 0;
4544 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4545 scoped_ptr<GLint[]> values(new GLint[num_written]);
4546 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4547 GetHelper(pname, values.get(), &num_written);
4549 for (GLsizei ii = 0; ii < num_written; ++ii) {
4550 params[ii] = static_cast<GLboolean>(values[ii]);
4553 pname = AdjustGetPname(pname);
4554 glGetBooleanv(pname, params);
4558 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4560 GLsizei num_written = 0;
4561 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4562 if (GetHelper(pname, NULL, &num_written)) {
4563 scoped_ptr<GLint[]> values(new GLint[num_written]);
4564 GetHelper(pname, values.get(), &num_written);
4565 for (GLsizei ii = 0; ii < num_written; ++ii) {
4566 params[ii] = static_cast<GLfloat>(values[ii]);
4569 pname = AdjustGetPname(pname);
4570 glGetFloatv(pname, params);
4575 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4577 GLsizei num_written;
4578 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4579 !GetHelper(pname, params, &num_written)) {
4580 pname = AdjustGetPname(pname);
4581 glGetIntegerv(pname, params);
4585 void GLES2DecoderImpl::DoGetProgramiv(
4586 GLuint program_id, GLenum pname, GLint* params) {
4587 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4591 program->GetProgramiv(pname, params);
4594 void GLES2DecoderImpl::DoGetBufferParameteriv(
4595 GLenum target, GLenum pname, GLint* params) {
4596 // Just delegate it. Some validation is actually done before this.
4597 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4598 &state_, target, pname, params);
4601 void GLES2DecoderImpl::DoBindAttribLocation(
4602 GLuint program_id, GLuint index, const char* name) {
4603 if (!StringIsValidForGLES(name)) {
4605 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4608 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4610 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4613 if (index >= group_->max_vertex_attribs()) {
4615 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4618 Program* program = GetProgramInfoNotShader(
4619 program_id, "glBindAttribLocation");
4623 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4624 glBindAttribLocation(program->service_id(), index, name);
4627 error::Error GLES2DecoderImpl::HandleBindAttribLocation(
4628 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
4629 GLuint program = static_cast<GLuint>(c.program);
4630 GLuint index = static_cast<GLuint>(c.index);
4631 uint32 name_size = c.data_size;
4632 const char* name = GetSharedMemoryAs<const char*>(
4633 c.name_shm_id, c.name_shm_offset, name_size);
4635 return error::kOutOfBounds;
4637 String name_str(name, name_size);
4638 DoBindAttribLocation(program, index, name_str.c_str());
4639 return error::kNoError;
4642 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4643 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4644 GLuint program = static_cast<GLuint>(c.program);
4645 GLuint index = static_cast<GLuint>(c.index);
4646 Bucket* bucket = GetBucket(c.name_bucket_id);
4647 if (!bucket || bucket->size() == 0) {
4648 return error::kInvalidArguments;
4650 std::string name_str;
4651 if (!bucket->GetAsString(&name_str)) {
4652 return error::kInvalidArguments;
4654 DoBindAttribLocation(program, index, name_str.c_str());
4655 return error::kNoError;
4658 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4659 GLuint program_id, GLint location, const char* name) {
4660 if (!StringIsValidForGLES(name)) {
4663 "glBindUniformLocationCHROMIUM", "Invalid character");
4666 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4668 GL_INVALID_OPERATION,
4669 "glBindUniformLocationCHROMIUM", "reserved prefix");
4672 if (location < 0 || static_cast<uint32>(location) >=
4673 (group_->max_fragment_uniform_vectors() +
4674 group_->max_vertex_uniform_vectors()) * 4) {
4677 "glBindUniformLocationCHROMIUM", "location out of range");
4680 Program* program = GetProgramInfoNotShader(
4681 program_id, "glBindUniformLocationCHROMIUM");
4685 if (!program->SetUniformLocationBinding(name, location)) {
4688 "glBindUniformLocationCHROMIUM", "location out of range");
4692 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4693 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
4694 GLuint program = static_cast<GLuint>(c.program);
4695 GLint location = static_cast<GLint>(c.location);
4696 uint32 name_size = c.data_size;
4697 const char* name = GetSharedMemoryAs<const char*>(
4698 c.name_shm_id, c.name_shm_offset, name_size);
4700 return error::kOutOfBounds;
4702 String name_str(name, name_size);
4703 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4704 return error::kNoError;
4707 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4708 uint32 immediate_data_size,
4709 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4710 GLuint program = static_cast<GLuint>(c.program);
4711 GLint location = static_cast<GLint>(c.location);
4712 Bucket* bucket = GetBucket(c.name_bucket_id);
4713 if (!bucket || bucket->size() == 0) {
4714 return error::kInvalidArguments;
4716 std::string name_str;
4717 if (!bucket->GetAsString(&name_str)) {
4718 return error::kInvalidArguments;
4720 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4721 return error::kNoError;
4724 error::Error GLES2DecoderImpl::HandleDeleteShader(
4725 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4726 GLuint client_id = c.shader;
4728 Shader* shader = GetShader(client_id);
4730 if (!shader->IsDeleted()) {
4731 glDeleteShader(shader->service_id());
4732 shader_manager()->MarkAsDeleted(shader);
4735 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4738 return error::kNoError;
4741 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4742 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4743 GLuint client_id = c.program;
4745 Program* program = GetProgram(client_id);
4747 if (!program->IsDeleted()) {
4748 program_manager()->MarkAsDeleted(shader_manager(), program);
4752 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4755 return error::kNoError;
4758 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4759 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4760 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4761 for (GLsizei ii = 0; ii < n; ++ii) {
4762 id_allocator->FreeID(ids[ii]);
4766 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4767 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4768 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4769 GLsizei n = static_cast<GLsizei>(c.n);
4771 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4772 return error::kOutOfBounds;
4774 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4775 c.ids_shm_id, c.ids_shm_offset, data_size);
4777 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4778 return error::kNoError;
4781 return error::kOutOfBounds;
4783 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4784 return error::kNoError;
4787 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4788 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4789 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4790 if (id_offset == 0) {
4791 for (GLsizei ii = 0; ii < n; ++ii) {
4792 ids[ii] = id_allocator->AllocateID();
4795 for (GLsizei ii = 0; ii < n; ++ii) {
4796 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4797 id_offset = ids[ii] + 1;
4802 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4803 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4804 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4805 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4806 GLsizei n = static_cast<GLsizei>(c.n);
4808 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4809 return error::kOutOfBounds;
4811 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4812 c.ids_shm_id, c.ids_shm_offset, data_size);
4814 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4815 return error::kNoError;
4818 return error::kOutOfBounds;
4820 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4821 return error::kNoError;
4824 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4825 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4826 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4827 for (GLsizei ii = 0; ii < n; ++ii) {
4828 if (!id_allocator->MarkAsUsed(ids[ii])) {
4829 for (GLsizei jj = 0; jj < ii; ++jj) {
4830 id_allocator->FreeID(ids[jj]);
4833 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4834 "attempt to register id that already exists");
4840 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4841 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4842 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4843 GLsizei n = static_cast<GLsizei>(c.n);
4845 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4846 return error::kOutOfBounds;
4848 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4849 c.ids_shm_id, c.ids_shm_offset, data_size);
4851 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4852 return error::kNoError;
4855 return error::kOutOfBounds;
4857 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4858 return error::kNoError;
4861 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4862 DCHECK(!ShouldDeferDraws());
4863 if (CheckBoundFramebuffersValid("glClear")) {
4867 return error::kNoError;
4870 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4871 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4872 GLuint client_renderbuffer_id) {
4873 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4876 GL_INVALID_OPERATION,
4877 "glFramebufferRenderbuffer", "no framebuffer bound");
4880 GLuint service_id = 0;
4881 Renderbuffer* renderbuffer = NULL;
4882 if (client_renderbuffer_id) {
4883 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4884 if (!renderbuffer) {
4886 GL_INVALID_OPERATION,
4887 "glFramebufferRenderbuffer", "unknown renderbuffer");
4890 service_id = renderbuffer->service_id();
4892 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4893 glFramebufferRenderbufferEXT(
4894 target, attachment, renderbuffertarget, service_id);
4895 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4896 if (error == GL_NO_ERROR) {
4897 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4899 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4900 framebuffer_state_.clear_state_dirty = true;
4905 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4906 if (SetCapabilityState(cap, false)) {
4911 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4912 if (SetCapabilityState(cap, true)) {
4917 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4918 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4919 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4920 glDepthRange(znear, zfar);
4923 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
4924 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4925 state_.sample_coverage_invert = (invert != 0);
4926 glSampleCoverage(state_.sample_coverage_value, invert);
4929 // Assumes framebuffer is complete.
4930 void GLES2DecoderImpl::ClearUnclearedAttachments(
4931 GLenum target, Framebuffer* framebuffer) {
4932 if (target == GL_READ_FRAMEBUFFER_EXT) {
4933 // bind this to the DRAW point, clear then bind back to READ
4934 // TODO(gman): I don't think there is any guarantee that an FBO that
4935 // is complete on the READ attachment will be complete as a DRAW
4937 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4938 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
4940 GLbitfield clear_bits = 0;
4941 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
4944 (GLES2Util::GetChannelsForFormat(
4945 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4947 glColorMask(true, true, true, true);
4948 clear_bits |= GL_COLOR_BUFFER_BIT;
4951 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4952 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4955 clear_bits |= GL_STENCIL_BUFFER_BIT;
4958 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4959 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4962 clear_bits |= GL_DEPTH_BUFFER_BIT;
4965 glDisable(GL_SCISSOR_TEST);
4966 glClear(clear_bits);
4968 framebuffer_manager()->MarkAttachmentsAsCleared(
4969 framebuffer, renderbuffer_manager(), texture_manager());
4971 RestoreClearState();
4973 if (target == GL_READ_FRAMEBUFFER_EXT) {
4974 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4975 Framebuffer* draw_framebuffer =
4976 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4977 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4978 GetBackbufferServiceId();
4979 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
4983 void GLES2DecoderImpl::RestoreClearState() {
4984 framebuffer_state_.clear_state_dirty = true;
4986 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4987 state_.color_clear_alpha);
4988 glClearStencil(state_.stencil_clear);
4989 glClearDepth(state_.depth_clear);
4990 if (state_.enable_flags.scissor_test) {
4991 glEnable(GL_SCISSOR_TEST);
4995 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
4996 Framebuffer* framebuffer =
4997 GetFramebufferInfoForTarget(target);
4999 return GL_FRAMEBUFFER_COMPLETE;
5001 GLenum completeness = framebuffer->IsPossiblyComplete();
5002 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5003 return completeness;
5005 return framebuffer->GetStatus(texture_manager(), target);
5008 void GLES2DecoderImpl::DoFramebufferTexture2D(
5009 GLenum target, GLenum attachment, GLenum textarget,
5010 GLuint client_texture_id, GLint level) {
5011 DoFramebufferTexture2DCommon(
5012 "glFramebufferTexture2D", target, attachment,
5013 textarget, client_texture_id, level, 0);
5016 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5017 GLenum target, GLenum attachment, GLenum textarget,
5018 GLuint client_texture_id, GLint level, GLsizei samples) {
5019 if (!features().multisampled_render_to_texture) {
5021 GL_INVALID_OPERATION,
5022 "glFramebufferTexture2DMultisample", "function not available");
5025 DoFramebufferTexture2DCommon(
5026 "glFramebufferTexture2DMultisample", target, attachment,
5027 textarget, client_texture_id, level, samples);
5030 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5031 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5032 GLuint client_texture_id, GLint level, GLsizei samples) {
5033 if (samples > renderbuffer_manager()->max_samples()) {
5036 "glFramebufferTexture2DMultisample", "samples too large");
5039 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5042 GL_INVALID_OPERATION,
5043 name, "no framebuffer bound.");
5046 GLuint service_id = 0;
5047 TextureRef* texture_ref = NULL;
5048 if (client_texture_id) {
5049 texture_ref = GetTexture(client_texture_id);
5052 GL_INVALID_OPERATION,
5053 name, "unknown texture_ref");
5056 service_id = texture_ref->service_id();
5059 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5062 name, "level out of range");
5067 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5069 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5071 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5073 if (features().use_img_for_multisampled_render_to_texture) {
5074 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5075 service_id, level, samples);
5077 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5078 service_id, level, samples);
5081 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5082 if (error == GL_NO_ERROR) {
5083 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5086 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5087 framebuffer_state_.clear_state_dirty = true;
5091 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5096 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5097 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5098 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5101 GL_INVALID_OPERATION,
5102 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5105 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5106 const Framebuffer::Attachment* attachment_object =
5107 framebuffer->GetAttachment(attachment);
5108 *params = attachment_object ? attachment_object->object_name() : 0;
5110 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5111 features().use_img_for_multisampled_render_to_texture) {
5112 pname = GL_TEXTURE_SAMPLES_IMG;
5114 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5118 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5119 GLenum target, GLenum pname, GLint* params) {
5120 Renderbuffer* renderbuffer =
5121 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5122 if (!renderbuffer) {
5124 GL_INVALID_OPERATION,
5125 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5129 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5130 *params = renderbuffer->internal_format();
5132 case GL_RENDERBUFFER_WIDTH:
5133 *params = renderbuffer->width();
5135 case GL_RENDERBUFFER_HEIGHT:
5136 *params = renderbuffer->height();
5138 case GL_RENDERBUFFER_SAMPLES_EXT:
5139 if (features().use_img_for_multisampled_render_to_texture) {
5140 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5143 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5147 glGetRenderbufferParameterivEXT(target, pname, params);
5152 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5153 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5154 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5155 GLbitfield mask, GLenum filter) {
5156 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5157 if (!features().chromium_framebuffer_multisample) {
5159 GL_INVALID_OPERATION,
5160 "glBlitFramebufferCHROMIUM", "function not available");
5164 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5168 glDisable(GL_SCISSOR_TEST);
5169 BlitFramebufferHelper(
5170 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5171 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
5174 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5175 const FeatureInfo* feature_info,
5178 GLenum internal_format,
5181 // TODO(sievers): This could be resolved at the GL binding level, but the
5182 // binding process is currently a bit too 'brute force'.
5183 if (feature_info->feature_flags().is_angle) {
5184 glRenderbufferStorageMultisampleANGLE(
5185 target, samples, internal_format, width, height);
5186 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5187 glRenderbufferStorageMultisample(
5188 target, samples, internal_format, width, height);
5190 glRenderbufferStorageMultisampleEXT(
5191 target, samples, internal_format, width, height);
5195 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5205 // TODO(sievers): This could be resolved at the GL binding level, but the
5206 // binding process is currently a bit too 'brute force'.
5207 if (feature_info_->feature_flags().is_angle) {
5208 glBlitFramebufferANGLE(
5209 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5210 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5212 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5214 glBlitFramebufferEXT(
5215 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5219 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5221 GLenum internalformat,
5224 if (samples > renderbuffer_manager()->max_samples()) {
5227 "glRenderbufferStorageMultisample", "samples too large");
5231 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5232 height > renderbuffer_manager()->max_renderbuffer_size()) {
5235 "glRenderbufferStorageMultisample", "dimensions too large");
5239 uint32 estimated_size = 0;
5240 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5241 width, height, samples, internalformat, &estimated_size)) {
5244 "glRenderbufferStorageMultisample", "dimensions too large");
5248 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5251 "glRenderbufferStorageMultisample", "out of memory");
5258 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5259 GLenum target, GLsizei samples, GLenum internalformat,
5260 GLsizei width, GLsizei height) {
5261 if (!features().chromium_framebuffer_multisample) {
5262 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5263 "glRenderbufferStorageMultisampleCHROMIUM",
5264 "function not available");
5268 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5269 if (!renderbuffer) {
5270 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5271 "glRenderbufferStorageMultisampleCHROMIUM",
5272 "no renderbuffer bound");
5276 if (!ValidateRenderbufferStorageMultisample(
5277 samples, internalformat, width, height)) {
5281 GLenum impl_format =
5282 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5284 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5285 "glRenderbufferStorageMultisampleCHROMIUM");
5286 RenderbufferStorageMultisampleHelper(
5287 feature_info_, target, samples, impl_format, width, height);
5289 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5290 if (error == GL_NO_ERROR) {
5292 if (workarounds().validate_multisample_buffer_allocation) {
5293 if (!VerifyMultisampleRenderbufferIntegrity(
5294 renderbuffer->service_id(), impl_format)) {
5297 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5302 // TODO(gman): If renderbuffers tracked which framebuffers they were
5303 // attached to we could just mark those framebuffers as not complete.
5304 framebuffer_manager()->IncFramebufferStateChangeCount();
5305 renderbuffer_manager()->SetInfo(
5306 renderbuffer, samples, internalformat, width, height);
5310 // This is the handler for multisampled_render_to_texture extensions.
5311 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5312 GLenum target, GLsizei samples, GLenum internalformat,
5313 GLsizei width, GLsizei height) {
5314 if (!features().multisampled_render_to_texture) {
5316 GL_INVALID_OPERATION,
5317 "glRenderbufferStorageMultisampleEXT", "function not available");
5321 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5322 if (!renderbuffer) {
5323 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5324 "glRenderbufferStorageMultisampleEXT",
5325 "no renderbuffer bound");
5329 if (!ValidateRenderbufferStorageMultisample(
5330 samples, internalformat, width, height)) {
5334 GLenum impl_format =
5335 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5337 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5338 if (features().use_img_for_multisampled_render_to_texture) {
5339 glRenderbufferStorageMultisampleIMG(
5340 target, samples, impl_format, width, height);
5342 glRenderbufferStorageMultisampleEXT(
5343 target, samples, impl_format, width, height);
5345 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5346 if (error == GL_NO_ERROR) {
5347 // TODO(gman): If renderbuffers tracked which framebuffers they were
5348 // attached to we could just mark those framebuffers as not complete.
5349 framebuffer_manager()->IncFramebufferStateChangeCount();
5350 renderbuffer_manager()->SetInfo(
5351 renderbuffer, samples, internalformat, width, height);
5355 // This function validates the allocation of a multisampled renderbuffer
5356 // by clearing it to a key color, blitting the contents to a texture, and
5357 // reading back the color to ensure it matches the key.
5358 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5359 GLuint renderbuffer, GLenum format) {
5361 // Only validate color buffers.
5362 // These formats have been selected because they are very common or are known
5363 // to be used by the WebGL backbuffer. If problems are observed with other
5364 // color formats they can be added here.
5375 GLint draw_framebuffer, read_framebuffer;
5377 // Cache framebuffer and texture bindings.
5378 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5379 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5381 if (!validation_texture_) {
5382 GLint bound_texture;
5383 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5385 // Create additional resources needed for the verification.
5386 glGenTextures(1, &validation_texture_);
5387 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5388 glGenFramebuffersEXT(1, &validation_fbo_);
5390 // Texture only needs to be 1x1.
5391 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5392 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5393 GL_UNSIGNED_BYTE, NULL);
5395 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5396 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5397 GL_TEXTURE_2D, validation_texture_, 0);
5399 glBindTexture(GL_TEXTURE_2D, bound_texture);
5402 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5403 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5404 GL_RENDERBUFFER, renderbuffer);
5406 // Cache current state and reset it to the values we require.
5407 GLboolean scissor_enabled = false;
5408 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5409 if (scissor_enabled)
5410 glDisable(GL_SCISSOR_TEST);
5412 GLboolean color_mask[4] = {true, true, true, true};
5413 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5414 glColorMask(true, true, true, true);
5416 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5417 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5418 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5420 // Clear the buffer to the desired key color.
5421 glClear(GL_COLOR_BUFFER_BIT);
5423 // Blit from the multisample buffer to a standard texture.
5424 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5425 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5427 BlitFramebufferHelper(
5428 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5430 // Read a pixel from the buffer.
5431 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5433 unsigned char pixel[3] = {0, 0, 0};
5434 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5436 // Detach the renderbuffer.
5437 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5438 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5439 GL_RENDERBUFFER, 0);
5441 // Restore cached state.
5442 if (scissor_enabled)
5443 glEnable(GL_SCISSOR_TEST);
5445 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5446 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5447 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5448 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5450 // Return true if the pixel matched the desired key color.
5451 return (pixel[0] == 0xFF &&
5456 void GLES2DecoderImpl::DoRenderbufferStorage(
5457 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5458 Renderbuffer* renderbuffer =
5459 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5460 if (!renderbuffer) {
5462 GL_INVALID_OPERATION,
5463 "glRenderbufferStorage", "no renderbuffer bound");
5467 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5468 height > renderbuffer_manager()->max_renderbuffer_size()) {
5470 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5474 uint32 estimated_size = 0;
5475 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5476 width, height, 1, internalformat, &estimated_size)) {
5478 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5482 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5484 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5488 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5489 glRenderbufferStorageEXT(
5491 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5495 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5496 if (error == GL_NO_ERROR) {
5497 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5498 // we could just mark those framebuffers as not complete.
5499 framebuffer_manager()->IncFramebufferStateChangeCount();
5500 renderbuffer_manager()->SetInfo(
5501 renderbuffer, 1, internalformat, width, height);
5505 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5506 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5507 Program* program = GetProgramInfoNotShader(
5508 program_id, "glLinkProgram");
5513 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5514 ShaderTranslator* vertex_translator = NULL;
5515 ShaderTranslator* fragment_translator = NULL;
5516 if (use_shader_translator_) {
5517 vertex_translator = vertex_translator_.get();
5518 fragment_translator = fragment_translator_.get();
5520 if (program->Link(shader_manager(),
5522 fragment_translator,
5523 workarounds().count_all_in_varyings_packing ?
5524 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5525 shader_cache_callback_)) {
5526 if (program == state_.current_program.get()) {
5527 if (workarounds().use_current_program_after_successful_link)
5528 glUseProgram(program->service_id());
5529 if (workarounds().clear_uniforms_before_first_program_use)
5530 program_manager()->ClearUniforms(program);
5535 void GLES2DecoderImpl::DoTexParameterf(
5536 GLenum target, GLenum pname, GLfloat param) {
5537 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5540 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5544 texture_manager()->SetParameterf(
5545 "glTexParameterf", GetErrorState(), texture, pname, param);
5548 void GLES2DecoderImpl::DoTexParameteri(
5549 GLenum target, GLenum pname, GLint param) {
5550 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5553 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5557 texture_manager()->SetParameteri(
5558 "glTexParameteri", GetErrorState(), texture, pname, param);
5561 void GLES2DecoderImpl::DoTexParameterfv(
5562 GLenum target, GLenum pname, const GLfloat* params) {
5563 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5566 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5570 texture_manager()->SetParameterf(
5571 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5574 void GLES2DecoderImpl::DoTexParameteriv(
5575 GLenum target, GLenum pname, const GLint* params) {
5576 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5580 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5584 texture_manager()->SetParameteri(
5585 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5588 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5589 if (!state_.current_program.get()) {
5590 // The program does not exist.
5592 GL_INVALID_OPERATION, function_name, "no program in use");
5595 if (!state_.current_program->InUse()) {
5597 GL_INVALID_OPERATION, function_name, "program not linked");
5603 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5604 GLint location, const char* function_name) {
5605 if (!CheckCurrentProgram(function_name)) {
5608 return location != -1;
5611 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5612 GLint fake_location,
5613 const char* function_name,
5614 Program::UniformApiType api_type,
5615 GLint* real_location,
5620 DCHECK(real_location);
5622 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5625 GLint array_index = -1;
5626 const Program::UniformInfo* info =
5627 state_.current_program->GetUniformInfoByFakeLocation(
5628 fake_location, real_location, &array_index);
5631 GL_INVALID_OPERATION, function_name, "unknown location");
5635 if ((api_type & info->accepts_api_type) == 0) {
5637 GL_INVALID_OPERATION, function_name,
5638 "wrong uniform function for type");
5641 if (*count > 1 && !info->is_array) {
5643 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5646 *count = std::min(info->size - array_index, *count);
5654 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5657 GLint real_location = -1;
5658 if (!PrepForSetUniformByLocation(fake_location,
5660 Program::kUniform1i,
5666 if (!state_.current_program->SetSamplers(
5667 state_.texture_units.size(), fake_location, 1, &v0)) {
5669 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5672 glUniform1i(real_location, v0);
5675 void GLES2DecoderImpl::DoUniform1iv(
5676 GLint fake_location, GLsizei count, const GLint *value) {
5678 GLint real_location = -1;
5679 if (!PrepForSetUniformByLocation(fake_location,
5681 Program::kUniform1i,
5687 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5688 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5689 if (!state_.current_program->SetSamplers(
5690 state_.texture_units.size(), fake_location, count, value)) {
5692 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5696 glUniform1iv(real_location, count, value);
5699 void GLES2DecoderImpl::DoUniform1fv(
5700 GLint fake_location, GLsizei count, const GLfloat* value) {
5702 GLint real_location = -1;
5703 if (!PrepForSetUniformByLocation(fake_location,
5705 Program::kUniform1f,
5711 if (type == GL_BOOL) {
5712 scoped_ptr<GLint[]> temp(new GLint[count]);
5713 for (GLsizei ii = 0; ii < count; ++ii) {
5714 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5716 DoUniform1iv(real_location, count, temp.get());
5718 glUniform1fv(real_location, count, value);
5722 void GLES2DecoderImpl::DoUniform2fv(
5723 GLint fake_location, GLsizei count, const GLfloat* value) {
5725 GLint real_location = -1;
5726 if (!PrepForSetUniformByLocation(fake_location,
5728 Program::kUniform2f,
5734 if (type == GL_BOOL_VEC2) {
5735 GLsizei num_values = count * 2;
5736 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5737 for (GLsizei ii = 0; ii < num_values; ++ii) {
5738 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5740 glUniform2iv(real_location, count, temp.get());
5742 glUniform2fv(real_location, count, value);
5746 void GLES2DecoderImpl::DoUniform3fv(
5747 GLint fake_location, GLsizei count, const GLfloat* value) {
5749 GLint real_location = -1;
5750 if (!PrepForSetUniformByLocation(fake_location,
5752 Program::kUniform3f,
5758 if (type == GL_BOOL_VEC3) {
5759 GLsizei num_values = count * 3;
5760 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5761 for (GLsizei ii = 0; ii < num_values; ++ii) {
5762 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5764 glUniform3iv(real_location, count, temp.get());
5766 glUniform3fv(real_location, count, value);
5770 void GLES2DecoderImpl::DoUniform4fv(
5771 GLint fake_location, GLsizei count, const GLfloat* value) {
5773 GLint real_location = -1;
5774 if (!PrepForSetUniformByLocation(fake_location,
5776 Program::kUniform4f,
5782 if (type == GL_BOOL_VEC4) {
5783 GLsizei num_values = count * 4;
5784 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5785 for (GLsizei ii = 0; ii < num_values; ++ii) {
5786 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5788 glUniform4iv(real_location, count, temp.get());
5790 glUniform4fv(real_location, count, value);
5794 void GLES2DecoderImpl::DoUniform2iv(
5795 GLint fake_location, GLsizei count, const GLint* value) {
5797 GLint real_location = -1;
5798 if (!PrepForSetUniformByLocation(fake_location,
5800 Program::kUniform2i,
5806 glUniform2iv(real_location, count, value);
5809 void GLES2DecoderImpl::DoUniform3iv(
5810 GLint fake_location, GLsizei count, const GLint* value) {
5812 GLint real_location = -1;
5813 if (!PrepForSetUniformByLocation(fake_location,
5815 Program::kUniform3i,
5821 glUniform3iv(real_location, count, value);
5824 void GLES2DecoderImpl::DoUniform4iv(
5825 GLint fake_location, GLsizei count, const GLint* value) {
5827 GLint real_location = -1;
5828 if (!PrepForSetUniformByLocation(fake_location,
5830 Program::kUniform4i,
5836 glUniform4iv(real_location, count, value);
5839 void GLES2DecoderImpl::DoUniformMatrix2fv(
5840 GLint fake_location, GLsizei count, GLboolean transpose,
5841 const GLfloat* value) {
5843 GLint real_location = -1;
5844 if (!PrepForSetUniformByLocation(fake_location,
5845 "glUniformMatrix2fv",
5846 Program::kUniformMatrix2f,
5852 glUniformMatrix2fv(real_location, count, transpose, value);
5855 void GLES2DecoderImpl::DoUniformMatrix3fv(
5856 GLint fake_location, GLsizei count, GLboolean transpose,
5857 const GLfloat* value) {
5859 GLint real_location = -1;
5860 if (!PrepForSetUniformByLocation(fake_location,
5861 "glUniformMatrix3fv",
5862 Program::kUniformMatrix3f,
5868 glUniformMatrix3fv(real_location, count, transpose, value);
5871 void GLES2DecoderImpl::DoUniformMatrix4fv(
5872 GLint fake_location, GLsizei count, GLboolean transpose,
5873 const GLfloat* value) {
5875 GLint real_location = -1;
5876 if (!PrepForSetUniformByLocation(fake_location,
5877 "glUniformMatrix4fv",
5878 Program::kUniformMatrix4f,
5884 glUniformMatrix4fv(real_location, count, transpose, value);
5887 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5888 GLuint service_id = 0;
5889 Program* program = NULL;
5891 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5895 if (!program->IsValid()) {
5896 // Program was not linked successfully. (ie, glLinkProgram)
5898 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5901 service_id = program->service_id();
5903 if (state_.current_program.get()) {
5904 program_manager()->UnuseProgram(shader_manager(),
5905 state_.current_program.get());
5907 state_.current_program = program;
5908 LogClientServiceMapping("glUseProgram", program_id, service_id);
5909 glUseProgram(service_id);
5910 if (state_.current_program.get()) {
5911 program_manager()->UseProgram(state_.current_program.get());
5912 if (workarounds().clear_uniforms_before_first_program_use)
5913 program_manager()->ClearUniforms(program);
5917 void GLES2DecoderImpl::RenderWarning(
5918 const char* filename, int line, const std::string& msg) {
5919 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
5922 void GLES2DecoderImpl::PerformanceWarning(
5923 const char* filename, int line, const std::string& msg) {
5924 logger_.LogMessage(filename, line,
5925 std::string("PERFORMANCE WARNING: ") + msg);
5928 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5929 Texture* texture, GLenum textarget) {
5930 // Image is already in use if texture is attached to a framebuffer.
5931 if (texture && !texture->IsAttachedToFramebuffer()) {
5932 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5934 ScopedGLErrorSuppressor suppressor(
5935 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5937 glBindTexture(textarget, texture->service_id());
5938 image->WillUseTexImage();
5939 RestoreCurrentTextureBindings(&state_, textarget);
5944 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
5945 Texture* texture, GLenum textarget) {
5946 // Image is still in use if texture is attached to a framebuffer.
5947 if (texture && !texture->IsAttachedToFramebuffer()) {
5948 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5950 ScopedGLErrorSuppressor suppressor(
5951 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
5953 glBindTexture(textarget, texture->service_id());
5954 image->DidUseTexImage();
5955 RestoreCurrentTextureBindings(&state_, textarget);
5960 bool GLES2DecoderImpl::PrepareTexturesForRender() {
5961 DCHECK(state_.current_program.get());
5962 if (!texture_manager()->HaveUnrenderableTextures() &&
5963 !texture_manager()->HaveImages()) {
5967 bool textures_set = false;
5968 const Program::SamplerIndices& sampler_indices =
5969 state_.current_program->sampler_indices();
5970 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5971 const Program::UniformInfo* uniform_info =
5972 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5973 DCHECK(uniform_info);
5974 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5975 GLuint texture_unit_index = uniform_info->texture_units[jj];
5976 if (texture_unit_index < state_.texture_units.size()) {
5977 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5978 TextureRef* texture_ref =
5979 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5980 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
5981 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
5982 textures_set = true;
5983 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5986 texture_manager()->black_texture_id(uniform_info->type));
5987 LOCAL_RENDER_WARNING(
5988 std::string("texture bound to texture unit ") +
5989 base::IntToString(texture_unit_index) +
5990 " is not renderable. It maybe non-power-of-2 and have"
5991 " incompatible texture filtering or is not"
5992 " 'texture complete'");
5996 if (textarget != GL_TEXTURE_CUBE_MAP) {
5997 Texture* texture = texture_ref->texture();
5998 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5999 if (image && !texture->IsAttachedToFramebuffer()) {
6000 ScopedGLErrorSuppressor suppressor(
6001 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6002 textures_set = true;
6003 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6004 image->WillUseTexImage();
6009 // else: should this be an error?
6012 return !textures_set;
6015 void GLES2DecoderImpl::RestoreStateForTextures() {
6016 DCHECK(state_.current_program.get());
6017 const Program::SamplerIndices& sampler_indices =
6018 state_.current_program->sampler_indices();
6019 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6020 const Program::UniformInfo* uniform_info =
6021 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6022 DCHECK(uniform_info);
6023 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6024 GLuint texture_unit_index = uniform_info->texture_units[jj];
6025 if (texture_unit_index < state_.texture_units.size()) {
6026 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6027 TextureRef* texture_ref =
6028 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6029 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6030 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6031 // Get the texture_ref info that was previously bound here.
6032 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6033 ? texture_unit.bound_texture_2d.get()
6034 : texture_unit.bound_texture_cube_map.get();
6035 glBindTexture(texture_unit.bind_target,
6036 texture_ref ? texture_ref->service_id() : 0);
6040 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6041 Texture* texture = texture_ref->texture();
6042 gfx::GLImage* image =
6043 texture->GetLevelImage(texture_unit.bind_target, 0);
6044 if (image && !texture->IsAttachedToFramebuffer()) {
6045 ScopedGLErrorSuppressor suppressor(
6046 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6047 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6048 image->DidUseTexImage();
6055 // Set the active texture back to whatever the user had it as.
6056 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6059 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6060 // Only check if there are some uncleared textures.
6061 if (!texture_manager()->HaveUnsafeTextures()) {
6065 // 1: Check all textures we are about to render with.
6066 if (state_.current_program.get()) {
6067 const Program::SamplerIndices& sampler_indices =
6068 state_.current_program->sampler_indices();
6069 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6070 const Program::UniformInfo* uniform_info =
6071 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6072 DCHECK(uniform_info);
6073 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6074 GLuint texture_unit_index = uniform_info->texture_units[jj];
6075 if (texture_unit_index < state_.texture_units.size()) {
6076 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6077 TextureRef* texture_ref =
6078 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6079 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6080 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6091 bool GLES2DecoderImpl::IsDrawValid(
6092 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
6093 // NOTE: We specifically do not check current_program->IsValid() because
6094 // it could never be invalid since glUseProgram would have failed. While
6095 // glLinkProgram could later mark the program as invalid the previous
6096 // valid program will still function if it is still the current program.
6097 if (!state_.current_program.get()) {
6098 // The program does not exist.
6099 // But GL says no ERROR.
6100 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6104 return state_.vertex_attrib_manager
6105 ->ValidateBindings(function_name,
6107 feature_info_.get(),
6108 state_.current_program.get(),
6109 max_vertex_accessed,
6113 bool GLES2DecoderImpl::SimulateAttrib0(
6114 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6118 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6121 const VertexAttrib* attrib =
6122 state_.vertex_attrib_manager->GetVertexAttrib(0);
6123 // If it's enabled or it's not used then we don't need to do anything.
6124 bool attrib_0_used =
6125 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6126 if (attrib->enabled() && attrib_0_used) {
6130 // Make a buffer with a single repeated vec4 value enough to
6131 // simulate the constant value that is supposed to be here.
6132 // This is required to emulate GLES2 on GL.
6133 GLuint num_vertices = max_vertex_accessed + 1;
6134 uint32 size_needed = 0;
6136 if (num_vertices == 0 ||
6137 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6138 size_needed > 0x7FFFFFFFU) {
6139 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6143 LOCAL_PERFORMANCE_WARNING(
6144 "Attribute 0 is disabled. This has signficant performance penalty");
6146 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6147 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6149 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6151 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6152 GLenum error = glGetError();
6153 if (error != GL_NO_ERROR) {
6155 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6160 const Vec4& value = state_.attrib_values[0];
6163 (!attrib_0_buffer_matches_value_ ||
6164 (value.v[0] != attrib_0_value_.v[0] ||
6165 value.v[1] != attrib_0_value_.v[1] ||
6166 value.v[2] != attrib_0_value_.v[2] ||
6167 value.v[3] != attrib_0_value_.v[3])))) {
6168 std::vector<Vec4> temp(num_vertices, value);
6169 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6170 attrib_0_buffer_matches_value_ = true;
6171 attrib_0_value_ = value;
6172 attrib_0_size_ = size_needed;
6175 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6177 if (attrib->divisor())
6178 glVertexAttribDivisorANGLE(0, 0);
6184 void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
6185 const VertexAttrib* attrib =
6186 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6187 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6188 Buffer* buffer = attrib->buffer();
6189 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6190 glVertexAttribPointer(
6191 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6192 attrib->gl_stride(), ptr);
6193 if (attrib->divisor())
6194 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6197 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6200 // Never touch vertex attribute 0's state (in particular, never
6201 // disable it) when running on desktop GL because it will never be
6203 if (attrib_index != 0 ||
6204 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6205 if (attrib->enabled()) {
6206 glEnableVertexAttribArray(attrib_index);
6208 glDisableVertexAttribArray(attrib_index);
6213 bool GLES2DecoderImpl::SimulateFixedAttribs(
6214 const char* function_name,
6215 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6218 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6221 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6225 LOCAL_PERFORMANCE_WARNING(
6226 "GL_FIXED attributes have a signficant performance penalty");
6228 // NOTE: we could be smart and try to check if a buffer is used
6229 // twice in 2 different attribs, find the overlapping parts and therefore
6230 // duplicate the minimum amount of data but this whole code path is not meant
6231 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6232 // tests so we just add to the buffer attrib used.
6234 GLuint elements_needed = 0;
6235 const VertexAttribManager::VertexAttribList& enabled_attribs =
6236 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6237 for (VertexAttribManager::VertexAttribList::const_iterator it =
6238 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6239 const VertexAttrib* attrib = *it;
6240 const Program::VertexAttrib* attrib_info =
6241 state_.current_program->GetAttribInfoByLocation(attrib->index());
6242 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6243 max_vertex_accessed);
6244 GLuint num_vertices = max_accessed + 1;
6245 if (num_vertices == 0) {
6247 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6251 attrib->CanAccess(max_accessed) &&
6252 attrib->type() == GL_FIXED) {
6253 uint32 elements_used = 0;
6254 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6255 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6257 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6263 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6264 uint32 size_needed = 0;
6265 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6266 size_needed > 0x7FFFFFFFU) {
6268 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6272 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6274 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6275 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6276 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6277 GLenum error = glGetError();
6278 if (error != GL_NO_ERROR) {
6280 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6285 // Copy the elements and convert to float
6286 GLintptr offset = 0;
6287 for (VertexAttribManager::VertexAttribList::const_iterator it =
6288 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6289 const VertexAttrib* attrib = *it;
6290 const Program::VertexAttrib* attrib_info =
6291 state_.current_program->GetAttribInfoByLocation(attrib->index());
6292 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6293 max_vertex_accessed);
6294 GLuint num_vertices = max_accessed + 1;
6295 if (num_vertices == 0) {
6297 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6301 attrib->CanAccess(max_accessed) &&
6302 attrib->type() == GL_FIXED) {
6303 int num_elements = attrib->size() * kSizeOfFloat;
6304 int size = num_elements * num_vertices;
6305 scoped_ptr<float[]> data(new float[size]);
6306 const int32* src = reinterpret_cast<const int32 *>(
6307 attrib->buffer()->GetRange(attrib->offset(), size));
6308 const int32* end = src + num_elements;
6309 float* dst = data.get();
6310 while (src != end) {
6311 *dst++ = static_cast<float>(*src++) / 65536.0f;
6313 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6314 glVertexAttribPointer(
6315 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6316 reinterpret_cast<GLvoid*>(offset));
6324 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6325 // There's no need to call glVertexAttribPointer because we shadow all the
6326 // settings and passing GL_FIXED to it will not work.
6329 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6333 error::Error GLES2DecoderImpl::DoDrawArrays(
6334 const char* function_name,
6339 GLsizei primcount) {
6340 error::Error error = WillAccessBoundFramebufferForDraw();
6341 if (error != error::kNoError)
6343 if (!validators_->draw_mode.IsValid(mode)) {
6344 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6345 return error::kNoError;
6348 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6349 return error::kNoError;
6351 if (primcount < 0) {
6352 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6353 return error::kNoError;
6355 if (!CheckBoundFramebuffersValid(function_name)) {
6356 return error::kNoError;
6358 // We have to check this here because the prototype for glDrawArrays
6359 // is GLint not GLsizei.
6361 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6362 return error::kNoError;
6365 if (count == 0 || (instanced && primcount == 0)) {
6366 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6367 return error::kNoError;
6370 GLuint max_vertex_accessed = first + count - 1;
6371 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6372 if (!ClearUnclearedTextures()) {
6373 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6374 return error::kNoError;
6376 bool simulated_attrib_0 = false;
6377 if (!SimulateAttrib0(
6378 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6379 return error::kNoError;
6381 bool simulated_fixed_attribs = false;
6382 if (SimulateFixedAttribs(
6383 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6385 bool textures_set = !PrepareTexturesForRender();
6387 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6389 glDrawArrays(mode, first, count);
6391 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6393 ProcessPendingQueries();
6395 RestoreStateForTextures();
6397 if (simulated_fixed_attribs) {
6398 RestoreStateForSimulatedFixedAttribs();
6401 if (simulated_attrib_0) {
6402 RestoreStateForAttrib(0);
6405 return error::kNoError;
6408 error::Error GLES2DecoderImpl::HandleDrawArrays(
6409 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6410 return DoDrawArrays("glDrawArrays",
6412 static_cast<GLenum>(c.mode),
6413 static_cast<GLint>(c.first),
6414 static_cast<GLsizei>(c.count),
6418 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6419 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6420 if (!features().angle_instanced_arrays) {
6422 GL_INVALID_OPERATION,
6423 "glDrawArraysInstancedANGLE", "function not available");
6424 return error::kNoError;
6426 return DoDrawArrays("glDrawArraysIntancedANGLE",
6428 static_cast<GLenum>(c.mode),
6429 static_cast<GLint>(c.first),
6430 static_cast<GLsizei>(c.count),
6431 static_cast<GLsizei>(c.primcount));
6434 error::Error GLES2DecoderImpl::DoDrawElements(
6435 const char* function_name,
6441 GLsizei primcount) {
6442 error::Error error = WillAccessBoundFramebufferForDraw();
6443 if (error != error::kNoError)
6445 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6447 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6448 return error::kNoError;
6452 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6453 return error::kNoError;
6456 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6457 return error::kNoError;
6459 if (!validators_->draw_mode.IsValid(mode)) {
6460 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6461 return error::kNoError;
6463 if (!validators_->index_type.IsValid(type)) {
6464 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6465 return error::kNoError;
6467 if (primcount < 0) {
6468 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6469 return error::kNoError;
6472 if (!CheckBoundFramebuffersValid(function_name)) {
6473 return error::kNoError;
6476 if (count == 0 || (instanced && primcount == 0)) {
6477 return error::kNoError;
6480 GLuint max_vertex_accessed;
6481 Buffer* element_array_buffer =
6482 state_.vertex_attrib_manager->element_array_buffer();
6484 if (!element_array_buffer->GetMaxValueForRange(
6485 offset, count, type, &max_vertex_accessed)) {
6487 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6488 return error::kNoError;
6491 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6492 if (!ClearUnclearedTextures()) {
6493 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6494 return error::kNoError;
6496 bool simulated_attrib_0 = false;
6497 if (!SimulateAttrib0(
6498 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6499 return error::kNoError;
6501 bool simulated_fixed_attribs = false;
6502 if (SimulateFixedAttribs(
6503 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6505 bool textures_set = !PrepareTexturesForRender();
6507 // TODO(gman): Refactor to hide these details in BufferManager or
6508 // VertexAttribManager.
6509 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6510 bool used_client_side_array = false;
6511 if (element_array_buffer->IsClientSideArray()) {
6512 used_client_side_array = true;
6513 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6514 indices = element_array_buffer->GetRange(offset, 0);
6517 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6519 glDrawElements(mode, count, type, indices);
6521 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6524 if (used_client_side_array) {
6525 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6526 element_array_buffer->service_id());
6529 ProcessPendingQueries();
6531 RestoreStateForTextures();
6533 if (simulated_fixed_attribs) {
6534 RestoreStateForSimulatedFixedAttribs();
6537 if (simulated_attrib_0) {
6538 RestoreStateForAttrib(0);
6541 return error::kNoError;
6544 error::Error GLES2DecoderImpl::HandleDrawElements(
6545 uint32 immediate_data_size, const cmds::DrawElements& c) {
6546 return DoDrawElements("glDrawElements",
6548 static_cast<GLenum>(c.mode),
6549 static_cast<GLsizei>(c.count),
6550 static_cast<GLenum>(c.type),
6551 static_cast<int32>(c.index_offset),
6555 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6556 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6557 if (!features().angle_instanced_arrays) {
6559 GL_INVALID_OPERATION,
6560 "glDrawElementsInstancedANGLE", "function not available");
6561 return error::kNoError;
6563 return DoDrawElements("glDrawElementsInstancedANGLE",
6565 static_cast<GLenum>(c.mode),
6566 static_cast<GLsizei>(c.count),
6567 static_cast<GLenum>(c.type),
6568 static_cast<int32>(c.index_offset),
6569 static_cast<GLsizei>(c.primcount));
6572 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6573 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6574 GLuint max_vertex_accessed = 0;
6575 Buffer* buffer = GetBuffer(buffer_id);
6577 // TODO(gman): Should this be a GL error or a command buffer error?
6579 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6581 if (!buffer->GetMaxValueForRange(
6582 offset, count, type, &max_vertex_accessed)) {
6583 // TODO(gman): Should this be a GL error or a command buffer error?
6585 GL_INVALID_OPERATION,
6586 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6589 return max_vertex_accessed;
6592 // Calls glShaderSource for the various versions of the ShaderSource command.
6593 // Assumes that data / data_size points to a piece of memory that is in range
6594 // of whatever context it came from (shared memory, immediate memory, bucket
6596 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6597 GLuint client_id, const char* data, uint32 data_size) {
6598 std::string str(data, data + data_size);
6599 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6601 return error::kNoError;
6603 // Note: We don't actually call glShaderSource here. We wait until
6604 // the call to glCompileShader.
6605 shader->UpdateSource(str.c_str());
6606 return error::kNoError;
6609 error::Error GLES2DecoderImpl::HandleShaderSource(
6610 uint32 immediate_data_size, const cmds::ShaderSource& c) {
6611 uint32 data_size = c.data_size;
6612 const char* data = GetSharedMemoryAs<const char*>(
6613 c.data_shm_id, c.data_shm_offset, data_size);
6615 return error::kOutOfBounds;
6617 return ShaderSourceHelper(c.shader, data, data_size);
6620 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6621 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6622 Bucket* bucket = GetBucket(c.data_bucket_id);
6623 if (!bucket || bucket->size() == 0) {
6624 return error::kInvalidArguments;
6626 return ShaderSourceHelper(
6627 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6628 bucket->size() - 1);
6631 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6632 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6633 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6637 ShaderTranslator* translator = NULL;
6638 if (use_shader_translator_) {
6639 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6640 vertex_translator_.get() : fragment_translator_.get();
6643 program_manager()->DoCompileShader(
6646 feature_info_->feature_flags().angle_translated_shader_source ?
6647 ProgramManager::kANGLE : ProgramManager::kGL);
6650 void GLES2DecoderImpl::DoGetShaderiv(
6651 GLuint shader_id, GLenum pname, GLint* params) {
6652 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6657 case GL_SHADER_SOURCE_LENGTH:
6658 *params = shader->source() ? shader->source()->size() + 1 : 0;
6660 case GL_COMPILE_STATUS:
6661 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6663 case GL_INFO_LOG_LENGTH:
6664 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6666 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6667 *params = shader->translated_source() ?
6668 shader->translated_source()->size() + 1 : 0;
6673 glGetShaderiv(shader->service_id(), pname, params);
6676 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6677 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6678 GLuint shader_id = c.shader;
6679 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6680 Bucket* bucket = CreateBucket(bucket_id);
6681 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6682 if (!shader || !shader->source()) {
6684 return error::kNoError;
6686 bucket->SetFromString(shader->source()->c_str());
6687 return error::kNoError;
6690 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6691 uint32 immediate_data_size,
6692 const cmds::GetTranslatedShaderSourceANGLE& c) {
6693 GLuint shader_id = c.shader;
6694 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6695 Bucket* bucket = CreateBucket(bucket_id);
6696 Shader* shader = GetShaderInfoNotProgram(
6697 shader_id, "glGetTranslatedShaderSourceANGLE");
6700 return error::kNoError;
6703 bucket->SetFromString(shader->translated_source() ?
6704 shader->translated_source()->c_str() : NULL);
6705 return error::kNoError;
6708 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6709 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6710 GLuint program_id = c.program;
6711 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6712 Bucket* bucket = CreateBucket(bucket_id);
6713 Program* program = GetProgramInfoNotShader(
6714 program_id, "glGetProgramInfoLog");
6715 if (!program || !program->log_info()) {
6716 bucket->SetFromString("");
6717 return error::kNoError;
6719 bucket->SetFromString(program->log_info()->c_str());
6720 return error::kNoError;
6723 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6724 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6725 GLuint shader_id = c.shader;
6726 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6727 Bucket* bucket = CreateBucket(bucket_id);
6728 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6729 if (!shader || !shader->log_info()) {
6730 bucket->SetFromString("");
6731 return error::kNoError;
6733 bucket->SetFromString(shader->log_info()->c_str());
6734 return error::kNoError;
6737 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6738 return state_.GetEnabled(cap);
6741 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6742 const Buffer* buffer = GetBuffer(client_id);
6743 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6746 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6747 const Framebuffer* framebuffer =
6748 GetFramebuffer(client_id);
6749 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6752 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6753 // IsProgram is true for programs as soon as they are created, until they are
6754 // deleted and no longer in use.
6755 const Program* program = GetProgram(client_id);
6756 return program != NULL && !program->IsDeleted();
6759 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6760 const Renderbuffer* renderbuffer =
6761 GetRenderbuffer(client_id);
6762 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6765 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6766 // IsShader is true for shaders as soon as they are created, until they
6767 // are deleted and not attached to any programs.
6768 const Shader* shader = GetShader(client_id);
6769 return shader != NULL && !shader->IsDeleted();
6772 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6773 const TextureRef* texture_ref = GetTexture(client_id);
6774 return texture_ref && texture_ref->texture()->IsValid();
6777 void GLES2DecoderImpl::DoAttachShader(
6778 GLuint program_client_id, GLint shader_client_id) {
6779 Program* program = GetProgramInfoNotShader(
6780 program_client_id, "glAttachShader");
6784 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6788 if (!program->AttachShader(shader_manager(), shader)) {
6790 GL_INVALID_OPERATION,
6792 "can not attach more than one shader of the same type.");
6795 glAttachShader(program->service_id(), shader->service_id());
6798 void GLES2DecoderImpl::DoDetachShader(
6799 GLuint program_client_id, GLint shader_client_id) {
6800 Program* program = GetProgramInfoNotShader(
6801 program_client_id, "glDetachShader");
6805 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6809 if (!program->DetachShader(shader_manager(), shader)) {
6811 GL_INVALID_OPERATION,
6812 "glDetachShader", "shader not attached to program");
6815 glDetachShader(program->service_id(), shader->service_id());
6818 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6819 Program* program = GetProgramInfoNotShader(
6820 program_client_id, "glValidateProgram");
6824 program->Validate();
6827 void GLES2DecoderImpl::GetVertexAttribHelper(
6828 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6830 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6831 Buffer* buffer = attrib->buffer();
6832 if (buffer && !buffer->IsDeleted()) {
6834 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6835 *params = client_id;
6839 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6840 *params = attrib->enabled();
6842 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6843 *params = attrib->size();
6845 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6846 *params = attrib->gl_stride();
6848 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6849 *params = attrib->type();
6851 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6852 *params = attrib->normalized();
6854 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6855 *params = attrib->divisor();
6863 void GLES2DecoderImpl::DoGetTexParameterfv(
6864 GLenum target, GLenum pname, GLfloat* params) {
6865 InitTextureMaxAnisotropyIfNeeded(target, pname);
6866 glGetTexParameterfv(target, pname, params);
6869 void GLES2DecoderImpl::DoGetTexParameteriv(
6870 GLenum target, GLenum pname, GLint* params) {
6871 InitTextureMaxAnisotropyIfNeeded(target, pname);
6872 glGetTexParameteriv(target, pname, params);
6875 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
6876 GLenum target, GLenum pname) {
6877 if (!workarounds().init_texture_max_anisotropy)
6879 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
6880 !validators_->texture_parameter.IsValid(pname)) {
6884 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
6888 GL_INVALID_OPERATION,
6889 "glGetTexParamter{fi}v", "unknown texture for target");
6892 Texture* texture = texture_ref->texture();
6893 texture->InitTextureMaxAnisotropyIfNeeded(target);
6896 void GLES2DecoderImpl::DoGetVertexAttribfv(
6897 GLuint index, GLenum pname, GLfloat* params) {
6898 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6901 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6905 case GL_CURRENT_VERTEX_ATTRIB: {
6906 const Vec4& value = state_.attrib_values[index];
6907 params[0] = value.v[0];
6908 params[1] = value.v[1];
6909 params[2] = value.v[2];
6910 params[3] = value.v[3];
6915 GetVertexAttribHelper(attrib, pname, &value);
6916 *params = static_cast<GLfloat>(value);
6922 void GLES2DecoderImpl::DoGetVertexAttribiv(
6923 GLuint index, GLenum pname, GLint* params) {
6924 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6927 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6931 case GL_CURRENT_VERTEX_ATTRIB: {
6932 const Vec4& value = state_.attrib_values[index];
6933 params[0] = static_cast<GLint>(value.v[0]);
6934 params[1] = static_cast<GLint>(value.v[1]);
6935 params[2] = static_cast<GLint>(value.v[2]);
6936 params[3] = static_cast<GLint>(value.v[3]);
6940 GetVertexAttribHelper(attrib, pname, params);
6945 bool GLES2DecoderImpl::SetVertexAttribValue(
6946 const char* function_name, GLuint index, const GLfloat* value) {
6947 if (index >= state_.attrib_values.size()) {
6948 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
6951 Vec4& v = state_.attrib_values[index];
6959 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6960 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6961 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6962 glVertexAttrib1f(index, v0);
6966 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
6967 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6968 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6969 glVertexAttrib2f(index, v0, v1);
6973 void GLES2DecoderImpl::DoVertexAttrib3f(
6974 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
6975 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6976 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6977 glVertexAttrib3f(index, v0, v1, v2);
6981 void GLES2DecoderImpl::DoVertexAttrib4f(
6982 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
6983 GLfloat v[4] = { v0, v1, v2, v3, };
6984 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6985 glVertexAttrib4f(index, v0, v1, v2, v3);
6989 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
6990 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6991 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6992 glVertexAttrib1fv(index, v);
6996 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
6997 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6998 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6999 glVertexAttrib2fv(index, v);
7003 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7004 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7005 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7006 glVertexAttrib3fv(index, v);
7010 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7011 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7012 glVertexAttrib4fv(index, v);
7016 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7017 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
7019 if (!state_.bound_array_buffer.get() ||
7020 state_.bound_array_buffer->IsDeleted()) {
7021 if (state_.vertex_attrib_manager.get() ==
7022 default_vertex_attrib_manager_.get()) {
7024 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7025 return error::kNoError;
7026 } else if (c.offset != 0) {
7029 "glVertexAttribPointer", "client side arrays are not allowed");
7030 return error::kNoError;
7034 GLuint indx = c.indx;
7035 GLint size = c.size;
7036 GLenum type = c.type;
7037 GLboolean normalized = c.normalized;
7038 GLsizei stride = c.stride;
7039 GLsizei offset = c.offset;
7040 const void* ptr = reinterpret_cast<const void*>(offset);
7041 if (!validators_->vertex_attrib_type.IsValid(type)) {
7042 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7043 return error::kNoError;
7045 if (!validators_->vertex_attrib_size.IsValid(size)) {
7047 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7048 return error::kNoError;
7050 if (indx >= group_->max_vertex_attribs()) {
7052 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7053 return error::kNoError;
7057 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7058 return error::kNoError;
7062 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7063 return error::kNoError;
7067 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7068 return error::kNoError;
7070 GLsizei component_size =
7071 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7072 if (offset % component_size > 0) {
7074 GL_INVALID_OPERATION,
7075 "glVertexAttribPointer", "offset not valid for type");
7076 return error::kNoError;
7078 if (stride % component_size > 0) {
7080 GL_INVALID_OPERATION,
7081 "glVertexAttribPointer", "stride not valid for type");
7082 return error::kNoError;
7084 state_.vertex_attrib_manager
7085 ->SetAttribInfo(indx,
7086 state_.bound_array_buffer.get(),
7091 stride != 0 ? stride : component_size * size,
7093 if (type != GL_FIXED) {
7094 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7096 return error::kNoError;
7099 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7101 state_.viewport_x = x;
7102 state_.viewport_y = y;
7103 state_.viewport_width = std::min(width, viewport_max_width_);
7104 state_.viewport_height = std::min(height, viewport_max_height_);
7105 glViewport(x, y, width, height);
7108 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7109 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7110 if (!features().angle_instanced_arrays) {
7112 GL_INVALID_OPERATION,
7113 "glVertexAttribDivisorANGLE", "function not available");
7115 GLuint index = c.index;
7116 GLuint divisor = c.divisor;
7117 if (index >= group_->max_vertex_attribs()) {
7120 "glVertexAttribDivisorANGLE", "index out of range");
7121 return error::kNoError;
7124 state_.vertex_attrib_manager->SetDivisor(
7127 glVertexAttribDivisorANGLE(index, divisor);
7128 return error::kNoError;
7131 template <typename pixel_data_type>
7132 static void WriteAlphaData(
7133 void *pixels, uint32 row_count, uint32 channel_count,
7134 uint32 alpha_channel_index, uint32 unpadded_row_size,
7135 uint32 padded_row_size, pixel_data_type alpha_value) {
7136 DCHECK_GT(channel_count, 0U);
7137 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7138 uint32 unpadded_row_size_in_elements =
7139 unpadded_row_size / sizeof(pixel_data_type);
7140 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7141 uint32 padded_row_size_in_elements =
7142 padded_row_size / sizeof(pixel_data_type);
7143 pixel_data_type* dst =
7144 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7145 for (uint32 yy = 0; yy < row_count; ++yy) {
7146 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7147 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7150 dst += padded_row_size_in_elements;
7154 void GLES2DecoderImpl::FinishReadPixels(
7155 const cmds::ReadPixels& c,
7157 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7158 GLsizei width = c.width;
7159 GLsizei height = c.height;
7160 GLenum format = c.format;
7161 GLenum type = c.type;
7162 typedef cmds::ReadPixels::Result Result;
7164 Result* result = NULL;
7165 if (c.result_shm_id != 0) {
7166 result = GetSharedMemoryAs<Result*>(
7167 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7170 glDeleteBuffersARB(1, &buffer);
7175 GLES2Util::ComputeImageDataSizes(
7176 width, height, format, type, state_.pack_alignment, &pixels_size,
7178 void* pixels = GetSharedMemoryAs<void*>(
7179 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7182 glDeleteBuffersARB(1, &buffer);
7188 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7190 if (features().map_buffer_range) {
7191 data = glMapBufferRange(
7192 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7194 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7196 memcpy(pixels, data, pixels_size);
7197 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7198 // have to restore the state.
7199 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7200 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7201 glDeleteBuffersARB(1, &buffer);
7204 if (result != NULL) {
7208 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7209 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7210 if ((channels_exist & 0x0008) == 0 &&
7211 workarounds().clear_alpha_in_readpixels) {
7212 // Set the alpha to 255 because some drivers are buggy in this regard.
7215 uint32 unpadded_row_size;
7216 uint32 padded_row_size;
7217 if (!GLES2Util::ComputeImageDataSizes(
7218 width, 2, format, type, state_.pack_alignment, &temp_size,
7219 &unpadded_row_size, &padded_row_size)) {
7223 uint32 channel_count = 0;
7224 uint32 alpha_channel = 0;
7237 if (channel_count > 0) {
7239 case GL_UNSIGNED_BYTE:
7240 WriteAlphaData<uint8>(
7241 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7242 padded_row_size, 0xFF);
7245 WriteAlphaData<float>(
7246 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7247 padded_row_size, 1.0f);
7250 WriteAlphaData<uint16>(
7251 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7252 padded_row_size, 0x3C00);
7260 error::Error GLES2DecoderImpl::HandleReadPixels(
7261 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7262 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7263 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7264 if (fbo_error != error::kNoError)
7268 GLsizei width = c.width;
7269 GLsizei height = c.height;
7270 GLenum format = c.format;
7271 GLenum type = c.type;
7272 GLboolean async = c.async;
7273 if (width < 0 || height < 0) {
7274 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7275 return error::kNoError;
7277 typedef cmds::ReadPixels::Result Result;
7279 if (!GLES2Util::ComputeImageDataSizes(
7280 width, height, format, type, state_.pack_alignment, &pixels_size,
7282 return error::kOutOfBounds;
7284 void* pixels = GetSharedMemoryAs<void*>(
7285 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7287 return error::kOutOfBounds;
7289 Result* result = NULL;
7290 if (c.result_shm_id != 0) {
7291 result = GetSharedMemoryAs<Result*>(
7292 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7294 return error::kOutOfBounds;
7298 if (!validators_->read_pixel_format.IsValid(format)) {
7299 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7300 return error::kNoError;
7302 if (!validators_->read_pixel_type.IsValid(type)) {
7303 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7304 return error::kNoError;
7306 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7307 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7308 // format and type are acceptable enums but not guaranteed to be supported
7309 // for this framebuffer. Have to ask gl if they are valid.
7310 GLint preferred_format = 0;
7311 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7312 GLint preferred_type = 0;
7313 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7314 if (format != static_cast<GLenum>(preferred_format) ||
7315 type != static_cast<GLenum>(preferred_type)) {
7317 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7318 "with the current read framebuffer");
7319 return error::kNoError;
7322 if (width == 0 || height == 0) {
7323 return error::kNoError;
7326 // Get the size of the current fbo or backbuffer.
7327 gfx::Size max_size = GetBoundReadFrameBufferSize();
7331 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7333 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7334 return error::kNoError;
7337 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7338 return error::kNoError;
7341 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7343 ScopedResolvedFrameBufferBinder binder(this, false, true);
7345 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7346 // The user requested an out of range area. Get the results 1 line
7349 uint32 unpadded_row_size;
7350 uint32 padded_row_size;
7351 if (!GLES2Util::ComputeImageDataSizes(
7352 width, 2, format, type, state_.pack_alignment, &temp_size,
7353 &unpadded_row_size, &padded_row_size)) {
7355 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7356 return error::kNoError;
7359 GLint dest_x_offset = std::max(-x, 0);
7360 uint32 dest_row_offset;
7361 if (!GLES2Util::ComputeImageDataSizes(
7362 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7365 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7366 return error::kNoError;
7369 // Copy each row into the larger dest rect.
7370 int8* dst = static_cast<int8*>(pixels);
7371 GLint read_x = std::max(0, x);
7372 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7373 GLint read_width = read_end_x - read_x;
7374 for (GLint yy = 0; yy < height; ++yy) {
7378 memset(dst, 0, unpadded_row_size);
7380 // If the row is in range, copy it.
7381 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7383 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7385 dst += padded_row_size;
7388 if (async && features().use_async_readpixels) {
7390 glGenBuffersARB(1, &buffer);
7391 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7392 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7393 GLenum error = glGetError();
7394 if (error == GL_NO_ERROR) {
7395 glReadPixels(x, y, width, height, format, type, 0);
7396 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7397 new FenceCallback()));
7398 WaitForReadPixels(base::Bind(
7399 &GLES2DecoderImpl::FinishReadPixels,
7400 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7401 <GLES2DecoderImpl>(this),
7403 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7404 return error::kNoError;
7406 // On error, unbind pack buffer and fall through to sync readpixels
7407 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7410 glReadPixels(x, y, width, height, format, type, pixels);
7412 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7413 if (error == GL_NO_ERROR) {
7414 if (result != NULL) {
7417 FinishReadPixels(c, 0);
7420 return error::kNoError;
7423 error::Error GLES2DecoderImpl::HandlePixelStorei(
7424 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7425 GLenum pname = c.pname;
7426 GLenum param = c.param;
7427 if (!validators_->pixel_store.IsValid(pname)) {
7428 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7429 return error::kNoError;
7432 case GL_PACK_ALIGNMENT:
7433 case GL_UNPACK_ALIGNMENT:
7434 if (!validators_->pixel_store_alignment.IsValid(param)) {
7436 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7437 return error::kNoError;
7440 case GL_UNPACK_FLIP_Y_CHROMIUM:
7441 unpack_flip_y_ = (param != 0);
7442 return error::kNoError;
7443 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7444 unpack_premultiply_alpha_ = (param != 0);
7445 return error::kNoError;
7446 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7447 unpack_unpremultiply_alpha_ = (param != 0);
7448 return error::kNoError;
7452 glPixelStorei(pname, param);
7454 case GL_PACK_ALIGNMENT:
7455 state_.pack_alignment = param;
7457 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7458 state_.pack_reverse_row_order = (param != 0);
7460 case GL_UNPACK_ALIGNMENT:
7461 state_.unpack_alignment = param;
7464 // Validation should have prevented us from getting here.
7468 return error::kNoError;
7471 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7472 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7473 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7474 if (!supports_post_sub_buffer_) {
7476 GL_INVALID_OPERATION,
7477 "glPostSubBufferCHROMIUM", "command not supported by surface");
7478 return error::kNoError;
7481 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7484 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7485 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7486 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7487 is_offscreen ? offscreen_size_ : surface_->GetSize());
7489 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7490 return error::kNoError;
7492 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7493 return error::kLostContext;
7497 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7498 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7499 const std::string& name_str) {
7500 if (!StringIsValidForGLES(name_str.c_str())) {
7502 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7503 return error::kNoError;
7505 Program* program = GetProgramInfoNotShader(
7506 client_id, "glGetAttribLocation");
7508 return error::kNoError;
7510 if (!program->IsValid()) {
7512 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7513 return error::kNoError;
7515 GLint* location = GetSharedMemoryAs<GLint*>(
7516 location_shm_id, location_shm_offset, sizeof(GLint));
7518 return error::kOutOfBounds;
7520 // Require the client to init this incase the context is lost and we are no
7521 // longer executing commands.
7522 if (*location != -1) {
7523 return error::kGenericError;
7525 *location = program->GetAttribLocation(name_str);
7526 return error::kNoError;
7529 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7530 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7531 uint32 name_size = c.data_size;
7532 const char* name = GetSharedMemoryAs<const char*>(
7533 c.name_shm_id, c.name_shm_offset, name_size);
7535 return error::kOutOfBounds;
7537 String name_str(name, name_size);
7538 return GetAttribLocationHelper(
7539 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7542 error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
7543 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
7544 Bucket* bucket = GetBucket(c.name_bucket_id);
7546 return error::kInvalidArguments;
7548 std::string name_str;
7549 if (!bucket->GetAsString(&name_str)) {
7550 return error::kInvalidArguments;
7552 return GetAttribLocationHelper(
7553 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7556 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7557 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7558 const std::string& name_str) {
7559 if (!StringIsValidForGLES(name_str.c_str())) {
7561 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7562 return error::kNoError;
7564 Program* program = GetProgramInfoNotShader(
7565 client_id, "glGetUniformLocation");
7567 return error::kNoError;
7569 if (!program->IsValid()) {
7571 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7572 return error::kNoError;
7574 GLint* location = GetSharedMemoryAs<GLint*>(
7575 location_shm_id, location_shm_offset, sizeof(GLint));
7577 return error::kOutOfBounds;
7579 // Require the client to init this incase the context is lost an we are no
7580 // longer executing commands.
7581 if (*location != -1) {
7582 return error::kGenericError;
7584 *location = program->GetUniformFakeLocation(name_str);
7585 return error::kNoError;
7588 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7589 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7590 uint32 name_size = c.data_size;
7591 const char* name = GetSharedMemoryAs<const char*>(
7592 c.name_shm_id, c.name_shm_offset, name_size);
7594 return error::kOutOfBounds;
7596 String name_str(name, name_size);
7597 return GetUniformLocationHelper(
7598 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7601 error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
7602 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
7603 Bucket* bucket = GetBucket(c.name_bucket_id);
7605 return error::kInvalidArguments;
7607 std::string name_str;
7608 if (!bucket->GetAsString(&name_str)) {
7609 return error::kInvalidArguments;
7611 return GetUniformLocationHelper(
7612 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7615 error::Error GLES2DecoderImpl::HandleGetString(
7616 uint32 immediate_data_size, const cmds::GetString& c) {
7617 GLenum name = static_cast<GLenum>(c.name);
7618 if (!validators_->string_type.IsValid(name)) {
7619 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7620 return error::kNoError;
7622 const char* str = reinterpret_cast<const char*>(glGetString(name));
7623 std::string extensions;
7626 str = "OpenGL ES 2.0 Chromium";
7628 case GL_SHADING_LANGUAGE_VERSION:
7629 str = "OpenGL ES GLSL ES 1.0 Chromium";
7633 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7634 // They are used by WEBGL_debug_renderer_info.
7635 if (!force_webgl_glsl_validation_)
7640 // For WebGL contexts, strip out the OES derivatives and
7641 // EXT frag depth extensions if they have not been enabled.
7642 if (force_webgl_glsl_validation_) {
7643 extensions = feature_info_->extensions();
7644 if (!derivatives_explicitly_enabled_) {
7645 size_t offset = extensions.find(kOESDerivativeExtension);
7646 if (std::string::npos != offset) {
7647 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7651 if (!frag_depth_explicitly_enabled_) {
7652 size_t offset = extensions.find(kEXTFragDepthExtension);
7653 if (std::string::npos != offset) {
7654 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7658 if (!draw_buffers_explicitly_enabled_) {
7659 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7660 if (std::string::npos != offset) {
7661 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7666 extensions = feature_info_->extensions().c_str();
7668 if (supports_post_sub_buffer_)
7669 extensions += " GL_CHROMIUM_post_sub_buffer";
7670 str = extensions.c_str();
7676 Bucket* bucket = CreateBucket(c.bucket_id);
7677 bucket->SetFromString(str);
7678 return error::kNoError;
7681 error::Error GLES2DecoderImpl::HandleBufferData(
7682 uint32 immediate_data_size, const cmds::BufferData& c) {
7683 GLenum target = static_cast<GLenum>(c.target);
7684 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7685 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7686 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7687 GLenum usage = static_cast<GLenum>(c.usage);
7688 const void* data = NULL;
7689 if (data_shm_id != 0 || data_shm_offset != 0) {
7690 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7692 return error::kOutOfBounds;
7695 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7696 return error::kNoError;
7699 void GLES2DecoderImpl::DoBufferSubData(
7700 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7701 // Just delegate it. Some validation is actually done before this.
7702 buffer_manager()->ValidateAndDoBufferSubData(
7703 &state_, target, offset, size, data);
7706 bool GLES2DecoderImpl::ClearLevel(
7707 unsigned service_id,
7708 unsigned bind_target,
7711 unsigned internal_format,
7716 bool is_texture_immutable) {
7717 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7718 if (feature_info_->feature_flags().angle_depth_texture &&
7719 (channels & GLES2Util::kDepth) != 0) {
7720 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7721 // on depth formats.
7723 glGenFramebuffersEXT(1, &fb);
7724 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7726 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7727 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7728 GL_DEPTH_ATTACHMENT;
7730 glFramebufferTexture2DEXT(
7731 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7732 // ANGLE promises a depth only attachment ok.
7733 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7734 GL_FRAMEBUFFER_COMPLETE) {
7741 glDisable(GL_SCISSOR_TEST);
7742 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7744 RestoreClearState();
7746 glDeleteFramebuffersEXT(1, &fb);
7747 Framebuffer* framebuffer =
7748 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7749 GLuint fb_service_id =
7750 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7751 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7755 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7758 uint32 padded_row_size;
7759 if (!GLES2Util::ComputeImageDataSizes(
7760 width, height, format, type, state_.unpack_alignment, &size,
7761 NULL, &padded_row_size)) {
7765 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7769 if (size > kMaxZeroSize) {
7770 if (kMaxZeroSize < padded_row_size) {
7771 // That'd be an awfully large texture.
7774 // We should never have a large total size with a zero row size.
7775 DCHECK_GT(padded_row_size, 0U);
7776 tile_height = kMaxZeroSize / padded_row_size;
7777 if (!GLES2Util::ComputeImageDataSizes(
7778 width, tile_height, format, type, state_.unpack_alignment, &size,
7783 tile_height = height;
7786 // Assumes the size has already been checked.
7787 scoped_ptr<char[]> zero(new char[size]);
7788 memset(zero.get(), 0, size);
7789 glBindTexture(bind_target, service_id);
7792 while (y < height) {
7793 GLint h = y + tile_height > height ? height - y : tile_height;
7794 if (is_texture_immutable || h != height) {
7795 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7798 target, level, internal_format, width, h, 0, format, type,
7803 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7804 &state_, bind_target);
7805 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7811 const int kS3TCBlockWidth = 4;
7812 const int kS3TCBlockHeight = 4;
7813 const int kS3TCDXT1BlockSize = 8;
7814 const int kS3TCDXT3AndDXT5BlockSize = 16;
7815 const int kETC1BlockWidth = 4;
7816 const int kETC1BlockHeight = 4;
7817 const int kETC1BlockSize = 8;
7819 bool IsValidDXTSize(GLint level, GLsizei size) {
7820 return (size == 1) ||
7821 (size == 2) || !(size % kS3TCBlockWidth);
7824 } // anonymous namespace.
7826 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7827 const char* function_name,
7828 GLsizei width, GLsizei height, GLenum format, size_t size) {
7829 unsigned int bytes_required = 0;
7832 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7833 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7834 int num_blocks_across =
7835 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7836 int num_blocks_down =
7837 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7838 int num_blocks = num_blocks_across * num_blocks_down;
7839 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7842 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7843 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7844 int num_blocks_across =
7845 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7846 int num_blocks_down =
7847 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7848 int num_blocks = num_blocks_across * num_blocks_down;
7849 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7852 case GL_ETC1_RGB8_OES: {
7853 int num_blocks_across =
7854 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7855 int num_blocks_down =
7856 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7857 int num_blocks = num_blocks_across * num_blocks_down;
7858 bytes_required = num_blocks * kETC1BlockSize;
7862 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7866 if (size != bytes_required) {
7868 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7875 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7876 const char* function_name,
7877 GLint level, GLsizei width, GLsizei height, GLenum format) {
7879 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7880 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7881 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7882 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7883 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7885 GL_INVALID_OPERATION, function_name,
7886 "width or height invalid for level");
7891 case GL_ETC1_RGB8_OES:
7892 if (width <= 0 || height <= 0) {
7894 GL_INVALID_OPERATION, function_name,
7895 "width or height invalid for level");
7904 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7905 const char* function_name,
7906 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7907 GLsizei width, GLsizei height, GLenum format,
7909 if (xoffset < 0 || yoffset < 0) {
7911 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7916 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7917 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7918 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7919 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7920 const int kBlockWidth = 4;
7921 const int kBlockHeight = 4;
7922 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7924 GL_INVALID_OPERATION, function_name,
7925 "xoffset or yoffset not multiple of 4");
7928 GLsizei tex_width = 0;
7929 GLsizei tex_height = 0;
7930 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7931 width - xoffset > tex_width ||
7932 height - yoffset > tex_height) {
7934 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7937 return ValidateCompressedTexDimensions(
7938 function_name, level, width, height, format);
7940 case GL_ETC1_RGB8_OES: {
7942 GL_INVALID_OPERATION, function_name,
7943 "not supported for ECT1_RGB8_OES textures");
7951 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7954 GLenum internal_format,
7960 // TODO(gman): Validate image_size is correct for width, height and format.
7961 if (!validators_->texture_target.IsValid(target)) {
7962 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7963 "glCompressedTexImage2D", target, "target");
7964 return error::kNoError;
7966 if (!validators_->compressed_texture_format.IsValid(
7968 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7969 "glCompressedTexImage2D", internal_format, "internal_format");
7970 return error::kNoError;
7972 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7976 "glCompressedTexImage2D", "dimensions out of range");
7977 return error::kNoError;
7979 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7984 "glCompressedTexImage2D", "unknown texture target");
7985 return error::kNoError;
7987 Texture* texture = texture_ref->texture();
7988 if (texture->IsImmutable()) {
7990 GL_INVALID_OPERATION,
7991 "glCompressedTexImage2D", "texture is immutable");
7992 return error::kNoError;
7995 if (!ValidateCompressedTexDimensions(
7996 "glCompressedTexImage2D", level, width, height, internal_format) ||
7997 !ValidateCompressedTexFuncData(
7998 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
7999 return error::kNoError;
8002 if (!EnsureGPUMemoryAvailable(image_size)) {
8004 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8005 return error::kNoError;
8008 if (texture->IsAttachedToFramebuffer()) {
8009 framebuffer_state_.clear_state_dirty = true;
8012 scoped_ptr<int8[]> zero;
8014 zero.reset(new int8[image_size]);
8015 memset(zero.get(), 0, image_size);
8018 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8019 glCompressedTexImage2D(
8020 target, level, internal_format, width, height, border, image_size, data);
8021 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8022 if (error == GL_NO_ERROR) {
8023 texture_manager()->SetLevelInfo(
8024 texture_ref, target, level, internal_format,
8025 width, height, 1, border, 0, 0, true);
8027 return error::kNoError;
8030 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8031 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
8032 GLenum target = static_cast<GLenum>(c.target);
8033 GLint level = static_cast<GLint>(c.level);
8034 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8035 GLsizei width = static_cast<GLsizei>(c.width);
8036 GLsizei height = static_cast<GLsizei>(c.height);
8037 GLint border = static_cast<GLint>(c.border);
8038 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8039 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8040 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8041 const void* data = NULL;
8042 if (data_shm_id != 0 || data_shm_offset != 0) {
8043 data = GetSharedMemoryAs<const void*>(
8044 data_shm_id, data_shm_offset, image_size);
8046 return error::kOutOfBounds;
8049 return DoCompressedTexImage2D(
8050 target, level, internal_format, width, height, border, image_size, data);
8053 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8054 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
8055 GLenum target = static_cast<GLenum>(c.target);
8056 GLint level = static_cast<GLint>(c.level);
8057 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8058 GLsizei width = static_cast<GLsizei>(c.width);
8059 GLsizei height = static_cast<GLsizei>(c.height);
8060 GLint border = static_cast<GLint>(c.border);
8061 Bucket* bucket = GetBucket(c.bucket_id);
8063 return error::kInvalidArguments;
8065 uint32 data_size = bucket->size();
8066 GLsizei imageSize = data_size;
8067 const void* data = bucket->GetData(0, data_size);
8069 return error::kInvalidArguments;
8071 return DoCompressedTexImage2D(
8072 target, level, internal_format, width, height, border,
8076 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8077 uint32 immediate_data_size,
8078 const cmds::CompressedTexSubImage2DBucket& c) {
8079 GLenum target = static_cast<GLenum>(c.target);
8080 GLint level = static_cast<GLint>(c.level);
8081 GLint xoffset = static_cast<GLint>(c.xoffset);
8082 GLint yoffset = static_cast<GLint>(c.yoffset);
8083 GLsizei width = static_cast<GLsizei>(c.width);
8084 GLsizei height = static_cast<GLsizei>(c.height);
8085 GLenum format = static_cast<GLenum>(c.format);
8086 Bucket* bucket = GetBucket(c.bucket_id);
8088 return error::kInvalidArguments;
8090 uint32 data_size = bucket->size();
8091 GLsizei imageSize = data_size;
8092 const void* data = bucket->GetData(0, data_size);
8094 return error::kInvalidArguments;
8096 if (!validators_->texture_target.IsValid(target)) {
8098 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8099 return error::kNoError;
8101 if (!validators_->compressed_texture_format.IsValid(format)) {
8102 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8103 "glCompressedTexSubImage2D", format, "format");
8104 return error::kNoError;
8108 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8109 return error::kNoError;
8113 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8114 return error::kNoError;
8116 if (imageSize < 0) {
8118 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8119 return error::kNoError;
8121 DoCompressedTexSubImage2D(
8122 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8123 return error::kNoError;
8126 error::Error GLES2DecoderImpl::HandleTexImage2D(
8127 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8128 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
8129 // Set as failed for now, but if it successed, this will be set to not failed.
8130 texture_state_.tex_image_2d_failed = true;
8131 GLenum target = static_cast<GLenum>(c.target);
8132 GLint level = static_cast<GLint>(c.level);
8133 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8134 // for internalformat.
8135 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8136 GLsizei width = static_cast<GLsizei>(c.width);
8137 GLsizei height = static_cast<GLsizei>(c.height);
8138 GLint border = static_cast<GLint>(c.border);
8139 GLenum format = static_cast<GLenum>(c.format);
8140 GLenum type = static_cast<GLenum>(c.type);
8141 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8142 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8144 if (!GLES2Util::ComputeImageDataSizes(
8145 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8147 return error::kOutOfBounds;
8149 const void* pixels = NULL;
8150 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8151 pixels = GetSharedMemoryAs<const void*>(
8152 pixels_shm_id, pixels_shm_offset, pixels_size);
8154 return error::kOutOfBounds;
8158 TextureManager::DoTextImage2DArguments args = {
8159 target, level, internal_format, width, height, border, format, type,
8160 pixels, pixels_size};
8161 texture_manager()->ValidateAndDoTexImage2D(
8162 &texture_state_, &state_, &framebuffer_state_, args);
8163 return error::kNoError;
8166 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8175 const void * data) {
8176 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8180 GL_INVALID_OPERATION,
8181 "glCompressedTexSubImage2D", "unknown texture for target");
8184 Texture* texture = texture_ref->texture();
8186 GLenum internal_format = 0;
8187 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8189 GL_INVALID_OPERATION,
8190 "glCompressedTexSubImage2D", "level does not exist.");
8193 if (internal_format != format) {
8195 GL_INVALID_OPERATION,
8196 "glCompressedTexSubImage2D", "format does not match internal format.");
8199 if (!texture->ValidForTexture(
8200 target, level, xoffset, yoffset, width, height, type)) {
8202 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8206 if (!ValidateCompressedTexFuncData(
8207 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8208 !ValidateCompressedTexSubDimensions(
8209 "glCompressedTexSubImage2D",
8210 target, level, xoffset, yoffset, width, height, format, texture)) {
8215 // Note: There is no need to deal with texture cleared tracking here
8216 // because the validation above means you can only get here if the level
8217 // is already a matching compressed format and in that case
8218 // CompressedTexImage2D already cleared the texture.
8219 glCompressedTexSubImage2D(
8220 target, level, xoffset, yoffset, width, height, format, image_size, data);
8224 GLint start, GLint range, GLint sourceRange,
8225 GLint* out_start, GLint* out_range) {
8232 GLint end = start + range;
8233 if (end > sourceRange) {
8234 range -= end - sourceRange;
8240 void GLES2DecoderImpl::DoCopyTexImage2D(
8243 GLenum internal_format,
8249 DCHECK(!ShouldDeferReads());
8250 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8254 GL_INVALID_OPERATION,
8255 "glCopyTexImage2D", "unknown texture for target");
8258 Texture* texture = texture_ref->texture();
8259 if (texture->IsImmutable()) {
8261 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8263 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8266 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8269 if (!texture_manager()->ValidateFormatAndTypeCombination(
8270 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8271 GL_UNSIGNED_BYTE)) {
8275 // Check we have compatible formats.
8276 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8277 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8278 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8280 if ((channels_needed & channels_exist) != channels_needed) {
8282 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8286 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8288 GL_INVALID_OPERATION,
8289 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8293 uint32 estimated_size = 0;
8294 if (!GLES2Util::ComputeImageDataSizes(
8295 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8296 &estimated_size, NULL, NULL)) {
8298 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8302 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8303 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8307 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8311 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8312 ScopedResolvedFrameBufferBinder binder(this, false, true);
8313 gfx::Size size = GetBoundReadFrameBufferSize();
8315 if (texture->IsAttachedToFramebuffer()) {
8316 framebuffer_state_.clear_state_dirty = true;
8319 // Clip to size to source dimensions
8322 GLint copyWidth = 0;
8323 GLint copyHeight = 0;
8324 Clip(x, width, size.width(), ©X, ©Width);
8325 Clip(y, height, size.height(), ©Y, ©Height);
8329 copyWidth != width ||
8330 copyHeight != height) {
8331 // some part was clipped so clear the texture.
8333 texture->service_id(), texture->target(),
8334 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8335 width, height, texture->IsImmutable())) {
8337 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8340 if (copyHeight > 0 && copyWidth > 0) {
8341 GLint dx = copyX - x;
8342 GLint dy = copyY - y;
8345 ScopedModifyPixels modify(texture_ref);
8346 glCopyTexSubImage2D(target, level,
8347 destX, destY, copyX, copyY,
8348 copyWidth, copyHeight);
8351 ScopedModifyPixels modify(texture_ref);
8352 glCopyTexImage2D(target, level, internal_format,
8353 copyX, copyY, copyWidth, copyHeight, border);
8355 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8356 if (error == GL_NO_ERROR) {
8357 texture_manager()->SetLevelInfo(
8358 texture_ref, target, level, internal_format, width, height, 1,
8359 border, internal_format, GL_UNSIGNED_BYTE, true);
8363 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8372 DCHECK(!ShouldDeferReads());
8373 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8377 GL_INVALID_OPERATION,
8378 "glCopyTexSubImage2D", "unknown texture for target");
8381 Texture* texture = texture_ref->texture();
8384 if (!texture->GetLevelType(target, level, &type, &format) ||
8385 !texture->ValidForTexture(
8386 target, level, xoffset, yoffset, width, height, type)) {
8388 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8391 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8393 GL_INVALID_OPERATION,
8394 "glCopyTexSubImage2D", "async upload pending for texture");
8398 // Check we have compatible formats.
8399 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8400 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8401 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8403 if (!channels_needed ||
8404 (channels_needed & channels_exist) != channels_needed) {
8406 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8410 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8412 GL_INVALID_OPERATION,
8413 "glCopySubImage2D", "can not be used with depth or stencil textures");
8417 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8421 ScopedResolvedFrameBufferBinder binder(this, false, true);
8422 gfx::Size size = GetBoundReadFrameBufferSize();
8425 GLint copyWidth = 0;
8426 GLint copyHeight = 0;
8427 Clip(x, width, size.width(), ©X, ©Width);
8428 Clip(y, height, size.height(), ©Y, ©Height);
8430 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8432 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8438 copyWidth != width ||
8439 copyHeight != height) {
8440 // some part was clipped so clear the sub rect.
8441 uint32 pixels_size = 0;
8442 if (!GLES2Util::ComputeImageDataSizes(
8443 width, height, format, type, state_.unpack_alignment, &pixels_size,
8446 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8449 scoped_ptr<char[]> zero(new char[pixels_size]);
8450 memset(zero.get(), 0, pixels_size);
8451 ScopedModifyPixels modify(texture_ref);
8453 target, level, xoffset, yoffset, width, height,
8454 format, type, zero.get());
8457 if (copyHeight > 0 && copyWidth > 0) {
8458 GLint dx = copyX - x;
8459 GLint dy = copyY - y;
8460 GLint destX = xoffset + dx;
8461 GLint destY = yoffset + dy;
8462 ScopedModifyPixels modify(texture_ref);
8463 glCopyTexSubImage2D(target, level,
8464 destX, destY, copyX, copyY,
8465 copyWidth, copyHeight);
8469 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8470 error::Error* error,
8471 const char* function_name,
8480 const void * data) {
8481 (*error) = error::kNoError;
8482 if (!validators_->texture_target.IsValid(target)) {
8483 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8487 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8491 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8494 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8498 GL_INVALID_OPERATION,
8499 function_name, "unknown texture for target");
8502 Texture* texture = texture_ref->texture();
8503 GLenum current_type = 0;
8504 GLenum internal_format = 0;
8505 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
8507 GL_INVALID_OPERATION, function_name, "level does not exist.");
8510 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8511 function_name, format, type, internal_format, level)) {
8514 if (type != current_type) {
8516 GL_INVALID_OPERATION,
8517 function_name, "type does not match type of texture.");
8520 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8522 GL_INVALID_OPERATION,
8523 function_name, "async upload pending for texture");
8526 if (!texture->ValidForTexture(
8527 target, level, xoffset, yoffset, width, height, type)) {
8528 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8531 if ((GLES2Util::GetChannelsForFormat(format) &
8532 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8534 GL_INVALID_OPERATION,
8535 function_name, "can not supply data for depth or stencil textures");
8539 (*error) = error::kOutOfBounds;
8545 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8554 const void * data) {
8555 error::Error error = error::kNoError;
8556 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8557 xoffset, yoffset, width, height, format, type, data)) {
8560 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8562 Texture* texture = texture_ref->texture();
8563 GLsizei tex_width = 0;
8564 GLsizei tex_height = 0;
8565 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8567 if (xoffset != 0 || yoffset != 0 ||
8568 width != tex_width || height != tex_height) {
8569 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8572 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8573 return error::kNoError;
8575 ScopedTextureUploadTimer timer(&texture_state_);
8577 target, level, xoffset, yoffset, width, height, format, type, data);
8578 return error::kNoError;
8581 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8582 !texture->IsImmutable()) {
8583 ScopedTextureUploadTimer timer(&texture_state_);
8584 GLenum internal_format;
8586 texture->GetLevelType(target, level, &tex_type, &internal_format);
8587 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8590 target, level, internal_format, width, height, 0, format, type, data);
8592 ScopedTextureUploadTimer timer(&texture_state_);
8594 target, level, xoffset, yoffset, width, height, format, type, data);
8596 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8597 return error::kNoError;
8600 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8601 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8602 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8603 GLboolean internal = static_cast<GLboolean>(c.internal);
8604 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8605 return error::kNoError;
8607 GLenum target = static_cast<GLenum>(c.target);
8608 GLint level = static_cast<GLint>(c.level);
8609 GLint xoffset = static_cast<GLint>(c.xoffset);
8610 GLint yoffset = static_cast<GLint>(c.yoffset);
8611 GLsizei width = static_cast<GLsizei>(c.width);
8612 GLsizei height = static_cast<GLsizei>(c.height);
8613 GLenum format = static_cast<GLenum>(c.format);
8614 GLenum type = static_cast<GLenum>(c.type);
8616 if (!GLES2Util::ComputeImageDataSizes(
8617 width, height, format, type, state_.unpack_alignment, &data_size,
8619 return error::kOutOfBounds;
8621 const void* pixels = GetSharedMemoryAs<const void*>(
8622 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8623 return DoTexSubImage2D(
8624 target, level, xoffset, yoffset, width, height, format, type, pixels);
8627 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8628 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8629 GLuint index = static_cast<GLuint>(c.index);
8630 GLenum pname = static_cast<GLenum>(c.pname);
8631 typedef cmds::GetVertexAttribPointerv::Result Result;
8632 Result* result = GetSharedMemoryAs<Result*>(
8633 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8635 return error::kOutOfBounds;
8637 // Check that the client initialized the result.
8638 if (result->size != 0) {
8639 return error::kInvalidArguments;
8641 if (!validators_->vertex_pointer.IsValid(pname)) {
8642 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8643 "glGetVertexAttribPointerv", pname, "pname");
8644 return error::kNoError;
8646 if (index >= group_->max_vertex_attribs()) {
8648 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8649 return error::kNoError;
8651 result->SetNumResults(1);
8652 *result->GetData() =
8653 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8654 return error::kNoError;
8657 bool GLES2DecoderImpl::GetUniformSetup(
8658 GLuint program_id, GLint fake_location,
8659 uint32 shm_id, uint32 shm_offset,
8660 error::Error* error, GLint* real_location,
8661 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8664 DCHECK(result_pointer);
8665 DCHECK(result_type);
8666 DCHECK(real_location);
8667 *error = error::kNoError;
8668 // Make sure we have enough room for the result on failure.
8669 SizedResult<GLint>* result;
8670 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8671 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8673 *error = error::kOutOfBounds;
8676 *result_pointer = result;
8677 // Set the result size to 0 so the client does not have to check for success.
8678 result->SetNumResults(0);
8679 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8683 if (!program->IsValid()) {
8684 // Program was not linked successfully. (ie, glLinkProgram)
8686 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8689 *service_id = program->service_id();
8690 GLint array_index = -1;
8691 const Program::UniformInfo* uniform_info =
8692 program->GetUniformInfoByFakeLocation(
8693 fake_location, real_location, &array_index);
8694 if (!uniform_info) {
8695 // No such location.
8697 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8700 GLenum type = uniform_info->type;
8701 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8703 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8706 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8707 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8709 *error = error::kOutOfBounds;
8712 result->size = size;
8713 *result_type = type;
8717 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8718 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8719 GLuint program = c.program;
8720 GLint fake_location = c.location;
8723 GLint real_location = -1;
8726 if (GetUniformSetup(
8727 program, fake_location, c.params_shm_id, c.params_shm_offset,
8728 &error, &real_location, &service_id, &result, &result_type)) {
8730 service_id, real_location,
8731 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8736 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8737 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8738 GLuint program = c.program;
8739 GLint fake_location = c.location;
8741 GLint real_location = -1;
8743 typedef cmds::GetUniformfv::Result Result;
8746 if (GetUniformSetup(
8747 program, fake_location, c.params_shm_id, c.params_shm_offset,
8748 &error, &real_location, &service_id,
8749 reinterpret_cast<void**>(&result), &result_type)) {
8750 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8751 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8752 GLsizei num_values = result->GetNumResults();
8753 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8754 glGetUniformiv(service_id, real_location, temp.get());
8755 GLfloat* dst = result->GetData();
8756 for (GLsizei ii = 0; ii < num_values; ++ii) {
8757 dst[ii] = (temp[ii] != 0);
8760 glGetUniformfv(service_id, real_location, result->GetData());
8766 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8767 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8768 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8769 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8770 typedef cmds::GetShaderPrecisionFormat::Result Result;
8771 Result* result = GetSharedMemoryAs<Result*>(
8772 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8774 return error::kOutOfBounds;
8776 // Check that the client initialized the result.
8777 if (result->success != 0) {
8778 return error::kInvalidArguments;
8780 if (!validators_->shader_type.IsValid(shader_type)) {
8781 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8782 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8783 return error::kNoError;
8785 if (!validators_->shader_precision.IsValid(precision_type)) {
8786 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8787 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8788 return error::kNoError;
8791 result->success = 1; // true
8793 GLint range[2] = { 0, 0 };
8794 GLint precision = 0;
8795 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8797 result->min_range = range[0];
8798 result->max_range = range[1];
8799 result->precision = precision;
8801 return error::kNoError;
8804 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8805 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8806 uint32 result_size = c.result_size;
8807 GLuint program_id = static_cast<GLuint>(c.program);
8808 Program* program = GetProgramInfoNotShader(
8809 program_id, "glGetAttachedShaders");
8811 return error::kNoError;
8813 typedef cmds::GetAttachedShaders::Result Result;
8814 uint32 max_count = Result::ComputeMaxResults(result_size);
8815 Result* result = GetSharedMemoryAs<Result*>(
8816 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8818 return error::kOutOfBounds;
8820 // Check that the client initialized the result.
8821 if (result->size != 0) {
8822 return error::kInvalidArguments;
8825 glGetAttachedShaders(
8826 program->service_id(), max_count, &count, result->GetData());
8827 for (GLsizei ii = 0; ii < count; ++ii) {
8828 if (!shader_manager()->GetClientId(result->GetData()[ii],
8829 &result->GetData()[ii])) {
8831 return error::kGenericError;
8834 result->SetNumResults(count);
8835 return error::kNoError;
8838 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8839 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8840 GLuint program_id = c.program;
8841 GLuint index = c.index;
8842 uint32 name_bucket_id = c.name_bucket_id;
8843 typedef cmds::GetActiveUniform::Result Result;
8844 Result* result = GetSharedMemoryAs<Result*>(
8845 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8847 return error::kOutOfBounds;
8849 // Check that the client initialized the result.
8850 if (result->success != 0) {
8851 return error::kInvalidArguments;
8853 Program* program = GetProgramInfoNotShader(
8854 program_id, "glGetActiveUniform");
8856 return error::kNoError;
8858 const Program::UniformInfo* uniform_info =
8859 program->GetUniformInfo(index);
8860 if (!uniform_info) {
8862 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8863 return error::kNoError;
8865 result->success = 1; // true.
8866 result->size = uniform_info->size;
8867 result->type = uniform_info->type;
8868 Bucket* bucket = CreateBucket(name_bucket_id);
8869 bucket->SetFromString(uniform_info->name.c_str());
8870 return error::kNoError;
8873 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
8874 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8875 GLuint program_id = c.program;
8876 GLuint index = c.index;
8877 uint32 name_bucket_id = c.name_bucket_id;
8878 typedef cmds::GetActiveAttrib::Result Result;
8879 Result* result = GetSharedMemoryAs<Result*>(
8880 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8882 return error::kOutOfBounds;
8884 // Check that the client initialized the result.
8885 if (result->success != 0) {
8886 return error::kInvalidArguments;
8888 Program* program = GetProgramInfoNotShader(
8889 program_id, "glGetActiveAttrib");
8891 return error::kNoError;
8893 const Program::VertexAttrib* attrib_info =
8894 program->GetAttribInfo(index);
8897 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
8898 return error::kNoError;
8900 result->success = 1; // true.
8901 result->size = attrib_info->size;
8902 result->type = attrib_info->type;
8903 Bucket* bucket = CreateBucket(name_bucket_id);
8904 bucket->SetFromString(attrib_info->name.c_str());
8905 return error::kNoError;
8908 error::Error GLES2DecoderImpl::HandleShaderBinary(
8909 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
8910 #if 1 // No binary shader support.
8911 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
8912 return error::kNoError;
8914 GLsizei n = static_cast<GLsizei>(c.n);
8916 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
8917 return error::kNoError;
8919 GLsizei length = static_cast<GLsizei>(c.length);
8921 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
8922 return error::kNoError;
8925 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8926 return error::kOutOfBounds;
8928 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8929 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8930 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8931 const void* binary = GetSharedMemoryAs<const void*>(
8932 c.binary_shm_id, c.binary_shm_offset, length);
8933 if (shaders == NULL || binary == NULL) {
8934 return error::kOutOfBounds;
8936 scoped_array<GLuint> service_ids(new GLuint[n]);
8937 for (GLsizei ii = 0; ii < n; ++ii) {
8938 Shader* shader = GetShader(shaders[ii]);
8940 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
8941 return error::kNoError;
8943 service_ids[ii] = shader->service_id();
8945 // TODO(gman): call glShaderBinary
8946 return error::kNoError;
8950 void GLES2DecoderImpl::DoSwapBuffers() {
8951 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8953 int this_frame_number = frame_number_++;
8954 // TRACE_EVENT for gpu tests:
8955 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
8956 TRACE_EVENT_SCOPE_THREAD,
8957 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8958 "width", (is_offscreen ? offscreen_size_.width() :
8959 surface_->GetSize().width()));
8960 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
8961 "offscreen", is_offscreen,
8962 "frame", this_frame_number);
8964 TRACE_EVENT_SYNTHETIC_DELAY("gpu.SwapBuffers");
8968 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8971 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8972 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8973 is_offscreen ? offscreen_size_ : surface_->GetSize());
8976 // If offscreen then don't actually SwapBuffers to the display. Just copy
8977 // the rendered frame to another frame buffer.
8979 TRACE_EVENT2("gpu", "Offscreen",
8980 "width", offscreen_size_.width(), "height", offscreen_size_.height());
8981 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8982 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8983 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8985 if (workarounds().needs_offscreen_buffer_workaround) {
8986 offscreen_saved_frame_buffer_->Create();
8990 // Allocate the offscreen saved color texture.
8991 DCHECK(offscreen_saved_color_format_);
8992 offscreen_saved_color_texture_->AllocateStorage(
8993 offscreen_size_, offscreen_saved_color_format_, false);
8995 offscreen_saved_frame_buffer_->AttachRenderTexture(
8996 offscreen_saved_color_texture_.get());
8997 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8998 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8999 GL_FRAMEBUFFER_COMPLETE) {
9000 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9001 << "because offscreen saved FBO was incomplete.";
9002 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9006 // Clear the offscreen color texture.
9007 // TODO(piman): Is this still necessary?
9009 ScopedFrameBufferBinder binder(this,
9010 offscreen_saved_frame_buffer_->id());
9011 glClearColor(0, 0, 0, 0);
9012 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9013 glDisable(GL_SCISSOR_TEST);
9014 glClear(GL_COLOR_BUFFER_BIT);
9015 RestoreClearState();
9019 UpdateParentTextureInfo();
9022 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9024 ScopedGLErrorSuppressor suppressor(
9025 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9027 if (IsOffscreenBufferMultisampled()) {
9028 // For multisampled buffers, resolve the frame buffer.
9029 ScopedResolvedFrameBufferBinder binder(this, true, false);
9031 ScopedFrameBufferBinder binder(this,
9032 offscreen_target_frame_buffer_->id());
9034 if (offscreen_target_buffer_preserved_) {
9035 // Copy the target frame buffer to the saved offscreen texture.
9036 offscreen_saved_color_texture_->Copy(
9037 offscreen_saved_color_texture_->size(),
9038 offscreen_saved_color_format_);
9040 // Flip the textures in the parent context via the texture manager.
9041 if (!!offscreen_saved_color_texture_info_.get())
9042 offscreen_saved_color_texture_info_->texture()->
9043 SetServiceId(offscreen_target_color_texture_->id());
9045 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9046 offscreen_target_frame_buffer_->AttachRenderTexture(
9047 offscreen_target_color_texture_.get());
9050 // Ensure the side effects of the copy are visible to the parent
9051 // context. There is no need to do this for ANGLE because it uses a
9052 // single D3D device for all contexts.
9053 if (!feature_info_->feature_flags().is_angle)
9057 if (!surface_->SwapBuffers()) {
9058 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9059 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9064 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9065 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
9066 Bucket* bucket = GetBucket(c.bucket_id);
9067 if (!bucket || bucket->size() == 0) {
9068 return error::kInvalidArguments;
9070 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9071 Result* result = GetSharedMemoryAs<Result*>(
9072 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9074 return error::kOutOfBounds;
9076 // Check that the client initialized the result.
9078 return error::kInvalidArguments;
9080 std::string feature_str;
9081 if (!bucket->GetAsString(&feature_str)) {
9082 return error::kInvalidArguments;
9085 // TODO(gman): make this some kind of table to function pointer thingy.
9086 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9087 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9088 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9089 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9090 // TODO(gman): decide how to remove the need for this const_cast.
9091 // I could make validators_ non const but that seems bad as this is the only
9092 // place it is needed. I could make some special friend class of validators
9093 // just to allow this to set them. That seems silly. I could refactor this
9094 // code to use the extension mechanism or the initialization attributes to
9095 // turn this feature on. Given that the only real point of this is to make
9096 // the conformance tests pass and given that there is lots of real work that
9097 // needs to be done it seems like refactoring for one to one of those
9098 // methods is a very low priority.
9099 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9100 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9101 force_webgl_glsl_validation_ = true;
9102 InitializeShaderTranslator();
9104 return error::kNoError;
9107 *result = 1; // true.
9108 return error::kNoError;
9111 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9112 uint32 immediate_data_size,
9113 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9114 Bucket* bucket = CreateBucket(c.bucket_id);
9115 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9116 info->Initialize(disallowed_features_);
9117 bucket->SetFromString(info->extensions().c_str());
9118 return error::kNoError;
9121 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9122 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9123 Bucket* bucket = GetBucket(c.bucket_id);
9124 if (!bucket || bucket->size() == 0) {
9125 return error::kInvalidArguments;
9127 std::string feature_str;
9128 if (!bucket->GetAsString(&feature_str)) {
9129 return error::kInvalidArguments;
9132 bool desire_webgl_glsl_validation =
9133 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9134 bool desire_standard_derivatives = false;
9135 bool desire_frag_depth = false;
9136 bool desire_draw_buffers = false;
9137 if (force_webgl_glsl_validation_) {
9138 desire_standard_derivatives =
9139 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9141 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9142 desire_draw_buffers =
9143 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9146 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9147 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9148 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9149 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9150 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9151 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9152 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9153 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9154 InitializeShaderTranslator();
9157 UpdateCapabilities();
9159 return error::kNoError;
9162 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9163 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9164 GLuint count = c.count;
9166 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9167 return error::kOutOfBounds;
9169 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9170 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9171 if (pnames == NULL) {
9172 return error::kOutOfBounds;
9175 // We have to copy them since we use them twice so the client
9176 // can't change them between the time we validate them and the time we use
9178 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9179 memcpy(enums.get(), pnames, pnames_size);
9181 // Count up the space needed for the result.
9182 uint32 num_results = 0;
9183 for (GLuint ii = 0; ii < count; ++ii) {
9184 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9186 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9187 "glGetMultipleCHROMIUM", enums[ii], "pname");
9188 return error::kNoError;
9190 // Num will never be more than 4.
9192 if (!SafeAddUint32(num_results, num, &num_results)) {
9193 return error::kOutOfBounds;
9197 uint32 result_size = 0;
9198 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9199 return error::kOutOfBounds;
9202 if (result_size != static_cast<uint32>(c.size)) {
9205 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9206 return error::kNoError;
9209 GLint* results = GetSharedMemoryAs<GLint*>(
9210 c.results_shm_id, c.results_shm_offset, result_size);
9211 if (results == NULL) {
9212 return error::kOutOfBounds;
9215 // Check the results have been cleared in case the context was lost.
9216 for (uint32 ii = 0; ii < num_results; ++ii) {
9218 return error::kInvalidArguments;
9223 GLint* start = results;
9224 for (GLuint ii = 0; ii < count; ++ii) {
9225 GLsizei num_written = 0;
9226 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9227 !GetHelper(enums[ii], results, &num_written)) {
9228 DoGetIntegerv(enums[ii], results);
9230 results += num_written;
9233 // Just to verify. Should this be a DCHECK?
9234 if (static_cast<uint32>(results - start) != num_results) {
9235 return error::kOutOfBounds;
9238 return error::kNoError;
9241 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9242 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9243 GLuint program_id = static_cast<GLuint>(c.program);
9244 uint32 bucket_id = c.bucket_id;
9245 Bucket* bucket = CreateBucket(bucket_id);
9246 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9247 Program* program = NULL;
9248 program = GetProgram(program_id);
9249 if (!program || !program->IsValid()) {
9250 return error::kNoError;
9252 program->GetProgramInfo(program_manager(), bucket);
9253 return error::kNoError;
9256 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9257 switch (reset_status_) {
9259 // TODO(kbr): improve the precision of the error code in this case.
9260 // Consider delegating to context for error code if MakeCurrent fails.
9261 return error::kUnknown;
9262 case GL_GUILTY_CONTEXT_RESET_ARB:
9263 return error::kGuilty;
9264 case GL_INNOCENT_CONTEXT_RESET_ARB:
9265 return error::kInnocent;
9266 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9267 return error::kUnknown;
9271 return error::kUnknown;
9274 bool GLES2DecoderImpl::WasContextLost() {
9275 if (reset_status_ != GL_NO_ERROR) {
9278 if (context_->WasAllocatedUsingRobustnessExtension()) {
9279 GLenum status = GL_NO_ERROR;
9280 if (has_robustness_extension_)
9281 status = glGetGraphicsResetStatusARB();
9282 if (status != GL_NO_ERROR) {
9283 // The graphics card was reset. Signal a lost context to the application.
9284 reset_status_ = status;
9285 reset_by_robustness_extension_ = true;
9286 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9287 << " context lost via ARB/EXT_robustness. Reset status = "
9288 << GLES2Util::GetStringEnum(status);
9295 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9296 return WasContextLost() && reset_by_robustness_extension_;
9299 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9300 // Only loses the context once.
9301 if (reset_status_ != GL_NO_ERROR) {
9305 // Marks this context as lost.
9306 reset_status_ = reset_status;
9307 current_decoder_error_ = error::kLostContext;
9310 error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9311 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
9312 GLenum current = static_cast<GLenum>(c.current);
9313 GLenum other = static_cast<GLenum>(c.other);
9314 if (!validators_->reset_status.IsValid(current)) {
9315 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9316 "glLoseContextCHROMIUM", current, "current");
9318 if (!validators_->reset_status.IsValid(other)) {
9319 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
9321 group_->LoseContexts(other);
9322 reset_status_ = current;
9323 current_decoder_error_ = error::kLostContext;
9324 return error::kLostContext;
9327 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9328 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9329 return error::kUnknownCommand;
9332 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9333 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9334 group_->mailbox_manager()->PullTextureUpdates();
9335 if (wait_sync_point_callback_.is_null())
9336 return error::kNoError;
9338 return wait_sync_point_callback_.Run(c.sync_point) ?
9339 error::kNoError : error::kDeferCommandUntilLater;
9342 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9343 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9344 if (surface_->DeferDraws())
9345 return error::kDeferCommandUntilLater;
9346 if (!surface_->SetBackbufferAllocation(false))
9347 return error::kLostContext;
9348 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9349 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9350 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9351 return error::kNoError;
9354 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9355 GLsizei n, const GLuint* client_ids) {
9356 for (GLsizei ii = 0; ii < n; ++ii) {
9357 if (query_manager_->GetQuery(client_ids[ii])) {
9361 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
9365 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9366 GLsizei n, const GLuint* client_ids) {
9367 for (GLsizei ii = 0; ii < n; ++ii) {
9368 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9369 if (query && !query->IsDeleted()) {
9370 ContextState::QueryMap::iterator it =
9371 state_.current_queries.find(query->target());
9372 if (it != state_.current_queries.end())
9373 state_.current_queries.erase(it);
9375 query->Destroy(true);
9376 query_manager_->RemoveQuery(client_ids[ii]);
9381 bool GLES2DecoderImpl::ProcessPendingQueries() {
9382 if (query_manager_.get() == NULL) {
9385 if (!query_manager_->ProcessPendingQueries()) {
9386 current_decoder_error_ = error::kOutOfBounds;
9388 return query_manager_->HavePendingQueries();
9391 // Note that if there are no pending readpixels right now,
9392 // this function will call the callback immediately.
9393 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9394 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9395 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9401 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9402 while (!pending_readpixel_fences_.empty() &&
9403 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9404 std::vector<base::Closure> callbacks =
9405 pending_readpixel_fences_.front()->callbacks;
9406 pending_readpixel_fences_.pop();
9407 for (size_t i = 0; i < callbacks.size(); i++) {
9413 bool GLES2DecoderImpl::HasMoreIdleWork() {
9414 return !pending_readpixel_fences_.empty() ||
9415 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9418 void GLES2DecoderImpl::PerformIdleWork() {
9419 ProcessPendingReadPixels();
9420 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9422 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9423 ProcessFinishedAsyncTransfers();
9426 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9427 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9428 GLenum target = static_cast<GLenum>(c.target);
9429 GLuint client_id = static_cast<GLuint>(c.id);
9430 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9431 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9434 case GL_COMMANDS_ISSUED_CHROMIUM:
9435 case GL_LATENCY_QUERY_CHROMIUM:
9436 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9437 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9438 case GL_GET_ERROR_QUERY_CHROMIUM:
9441 if (!features().occlusion_query_boolean) {
9443 GL_INVALID_OPERATION, "glBeginQueryEXT",
9444 "not enabled for occlusion queries");
9445 return error::kNoError;
9450 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9452 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9453 return error::kNoError;
9456 if (client_id == 0) {
9457 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9458 return error::kNoError;
9461 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9463 // TODO(gman): Decide if we need this check.
9465 // Checks id was made by glGenQueries
9467 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9468 // for all Query ids but from the POV of the command buffer service maybe
9471 // The client can enforce this. I don't think the service cares.
9473 // IdAllocatorInterface* id_allocator =
9474 // group_->GetIdAllocator(id_namespaces::kQueries);
9475 // if (!id_allocator->InUse(client_id)) {
9476 // LOCAL_SET_GL_ERROR(
9477 // GL_INVALID_OPERATION,
9478 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
9479 // return error::kNoError;
9481 query = query_manager_->CreateQuery(
9482 target, client_id, sync_shm_id, sync_shm_offset);
9485 if (query->target() != target) {
9487 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9488 return error::kNoError;
9489 } else if (query->shm_id() != sync_shm_id ||
9490 query->shm_offset() != sync_shm_offset) {
9491 DLOG(ERROR) << "Shared memory used by query not the same as before";
9492 return error::kInvalidArguments;
9495 if (!query_manager_->BeginQuery(query)) {
9496 return error::kOutOfBounds;
9499 state_.current_queries[target] = query;
9500 return error::kNoError;
9503 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9504 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9505 GLenum target = static_cast<GLenum>(c.target);
9506 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9507 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9509 if (it == state_.current_queries.end()) {
9511 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9512 return error::kNoError;
9515 QueryManager::Query* query = it->second.get();
9516 if (!query_manager_->EndQuery(query, submit_count)) {
9517 return error::kOutOfBounds;
9520 query_manager_->ProcessPendingTransferQueries();
9522 state_.current_queries.erase(it);
9523 return error::kNoError;
9526 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9527 GLsizei n, const GLuint* client_ids) {
9528 for (GLsizei ii = 0; ii < n; ++ii) {
9529 if (GetVertexAttribManager(client_ids[ii])) {
9534 if (!features().native_vertex_array_object) {
9536 for (GLsizei ii = 0; ii < n; ++ii) {
9537 CreateVertexAttribManager(client_ids[ii], 0);
9540 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9542 glGenVertexArraysOES(n, service_ids.get());
9543 for (GLsizei ii = 0; ii < n; ++ii) {
9544 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9551 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9552 GLsizei n, const GLuint* client_ids) {
9553 for (GLsizei ii = 0; ii < n; ++ii) {
9554 VertexAttribManager* vao =
9555 GetVertexAttribManager(client_ids[ii]);
9556 if (vao && !vao->IsDeleted()) {
9557 if (state_.vertex_attrib_manager.get() == vao) {
9558 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
9560 RemoveVertexAttribManager(client_ids[ii]);
9565 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9566 VertexAttribManager* vao = NULL;
9567 GLuint service_id = 0;
9568 if (client_id != 0) {
9569 vao = GetVertexAttribManager(client_id);
9571 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9572 // only allows names that have been previously generated. As such, we do
9573 // not generate new names here.
9575 GL_INVALID_OPERATION,
9576 "glBindVertexArrayOES", "bad vertex array id.");
9577 current_decoder_error_ = error::kNoError;
9580 service_id = vao->service_id();
9583 vao = default_vertex_attrib_manager_.get();
9586 // Only set the VAO state if it's changed
9587 if (state_.vertex_attrib_manager.get() != vao) {
9588 state_.vertex_attrib_manager = vao;
9589 if (!features().native_vertex_array_object) {
9590 EmulateVertexArrayState();
9592 glBindVertexArrayOES(service_id);
9597 // Used when OES_vertex_array_object isn't natively supported
9598 void GLES2DecoderImpl::EmulateVertexArrayState() {
9599 // Setup the Vertex attribute state
9600 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9601 RestoreStateForAttrib(vv);
9604 // Setup the element buffer
9605 Buffer* element_array_buffer =
9606 state_.vertex_attrib_manager->element_array_buffer();
9607 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9608 element_array_buffer ? element_array_buffer->service_id() : 0);
9611 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9612 const VertexAttribManager* vao =
9613 GetVertexAttribManager(client_id);
9614 return vao && vao->IsValid() && !vao->IsDeleted();
9617 #if defined(OS_MACOSX)
9618 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9619 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9621 if (it != texture_to_io_surface_map_.end()) {
9622 // Found a previous IOSurface bound to this texture; release it.
9623 CFTypeRef surface = it->second;
9625 texture_to_io_surface_map_.erase(it);
9630 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9631 GLenum target, GLsizei width, GLsizei height,
9632 GLuint io_surface_id, GLuint plane) {
9633 #if defined(OS_MACOSX)
9634 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9636 GL_INVALID_OPERATION,
9637 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9641 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9642 if (!surface_support) {
9644 GL_INVALID_OPERATION,
9645 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
9649 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9650 // This might be supported in the future, and if we could require
9651 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9652 // could delete a lot of code. For now, perform strict validation so we
9653 // know what's going on.
9655 GL_INVALID_OPERATION,
9656 "glTexImageIOSurface2DCHROMIUM",
9657 "requires TEXTURE_RECTANGLE_ARB target");
9661 // Default target might be conceptually valid, but disallow it to avoid
9663 TextureRef* texture_ref =
9664 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9667 GL_INVALID_OPERATION,
9668 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9672 // Look up the new IOSurface. Note that because of asynchrony
9673 // between processes this might fail; during live resizing the
9674 // plugin process might allocate and release an IOSurface before
9675 // this process gets a chance to look it up. Hold on to any old
9676 // IOSurface in this case.
9677 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9680 GL_INVALID_OPERATION,
9681 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9685 // Release any IOSurface previously bound to this texture.
9686 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9688 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9689 texture_to_io_surface_map_.insert(
9690 std::make_pair(texture_ref->service_id(), surface));
9692 CGLContextObj context =
9693 static_cast<CGLContextObj>(context_->GetHandle());
9695 CGLError err = surface_support->CGLTexImageIOSurface2D(
9702 GL_UNSIGNED_INT_8_8_8_8_REV,
9706 if (err != kCGLNoError) {
9708 GL_INVALID_OPERATION,
9709 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9713 texture_manager()->SetLevelInfo(
9714 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9715 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9718 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9719 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9723 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9724 switch (internalformat) {
9735 case GL_LUMINANCE8_ALPHA8_EXT:
9736 return GL_LUMINANCE_ALPHA;
9737 case GL_LUMINANCE8_EXT:
9738 return GL_LUMINANCE;
9741 case GL_RGBA32F_EXT:
9745 case GL_ALPHA32F_EXT:
9747 case GL_LUMINANCE32F_EXT:
9748 return GL_LUMINANCE;
9749 case GL_LUMINANCE_ALPHA32F_EXT:
9750 return GL_LUMINANCE_ALPHA;
9751 case GL_RGBA16F_EXT:
9755 case GL_ALPHA16F_EXT:
9757 case GL_LUMINANCE16F_EXT:
9758 return GL_LUMINANCE;
9759 case GL_LUMINANCE_ALPHA16F_EXT:
9760 return GL_LUMINANCE_ALPHA;
9768 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9769 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9770 GLenum internal_format, GLenum dest_type) {
9771 TextureRef* dest_texture_ref = GetTexture(dest_id);
9772 TextureRef* source_texture_ref = GetTexture(source_id);
9774 if (!source_texture_ref || !dest_texture_ref) {
9776 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9780 if (GL_TEXTURE_2D != target) {
9782 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9786 Texture* source_texture = source_texture_ref->texture();
9787 Texture* dest_texture = dest_texture_ref->texture();
9788 if (dest_texture->target() != GL_TEXTURE_2D ||
9789 (source_texture->target() != GL_TEXTURE_2D &&
9790 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9791 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9792 "glCopyTextureCHROMIUM",
9793 "invalid texture target binding");
9797 int source_width, source_height, dest_width, dest_height;
9799 gfx::GLImage* image =
9800 source_texture->GetLevelImage(source_texture->target(), 0);
9802 gfx::Size size = image->GetSize();
9803 source_width = size.width();
9804 source_height = size.height();
9805 if (source_width <= 0 || source_height <= 0) {
9808 "glCopyTextureChromium", "invalid image size");
9812 if (!source_texture->GetLevelSize(
9813 source_texture->target(), 0, &source_width, &source_height)) {
9814 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9815 "glCopyTextureChromium",
9816 "source texture has no level 0");
9820 // Check that this type of texture is allowed.
9821 if (!texture_manager()->ValidForTarget(
9822 source_texture->target(), level, source_width, source_height, 1)) {
9824 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9829 // Clear the source texture if necessary.
9830 if (!texture_manager()->ClearTextureLevel(
9831 this, source_texture_ref, source_texture->target(), 0)) {
9833 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
9837 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9838 // needed because it takes 10s of milliseconds to initialize.
9839 if (!copy_texture_CHROMIUM_.get()) {
9840 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9841 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9842 copy_texture_CHROMIUM_->Initialize(this);
9843 RestoreCurrentFramebufferBindings();
9844 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9848 GLenum dest_type_previous;
9849 GLenum dest_internal_format;
9850 bool dest_level_defined = dest_texture->GetLevelSize(
9851 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9853 if (dest_level_defined) {
9854 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9855 &dest_internal_format);
9858 // Resize the destination texture to the dimensions of the source texture.
9859 if (!dest_level_defined || dest_width != source_width ||
9860 dest_height != source_height ||
9861 dest_internal_format != internal_format ||
9862 dest_type_previous != dest_type) {
9863 // Ensure that the glTexImage2D succeeds.
9864 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9865 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9867 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9868 0, internal_format, dest_type, NULL);
9869 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9870 if (error != GL_NO_ERROR) {
9871 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
9875 texture_manager()->SetLevelInfo(
9876 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9877 source_height, 1, 0, internal_format, dest_type, true);
9879 texture_manager()->SetLevelCleared(
9880 dest_texture_ref, GL_TEXTURE_2D, level, true);
9883 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9884 ScopedModifyPixels modify(dest_texture_ref);
9886 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9887 // before presenting.
9888 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9889 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9890 // instead of using default matrix crbug.com/226218.
9891 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9892 0.0f, 1.0f, 0.0f, 0.0f,
9893 0.0f, 0.0f, 1.0f, 0.0f,
9894 0.0f, 0.0f, 0.0f, 1.0f};
9895 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9897 source_texture->target(),
9898 dest_texture->target(),
9899 source_texture->service_id(),
9900 dest_texture->service_id(), level,
9901 source_width, source_height,
9903 unpack_premultiply_alpha_,
9904 unpack_unpremultiply_alpha_,
9907 copy_texture_CHROMIUM_->DoCopyTexture(
9909 source_texture->target(),
9910 dest_texture->target(),
9911 source_texture->service_id(),
9912 dest_texture->service_id(), level,
9913 source_width, source_height,
9915 unpack_premultiply_alpha_,
9916 unpack_unpremultiply_alpha_);
9919 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
9922 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9923 switch (internalformat) {
9925 return GL_UNSIGNED_SHORT_5_6_5;
9927 return GL_UNSIGNED_SHORT_4_4_4_4;
9929 return GL_UNSIGNED_SHORT_5_5_5_1;
9931 return GL_UNSIGNED_BYTE;
9933 return GL_UNSIGNED_BYTE;
9934 case GL_LUMINANCE8_ALPHA8_EXT:
9935 return GL_UNSIGNED_BYTE;
9936 case GL_LUMINANCE8_EXT:
9937 return GL_UNSIGNED_BYTE;
9939 return GL_UNSIGNED_BYTE;
9940 case GL_RGBA32F_EXT:
9944 case GL_ALPHA32F_EXT:
9946 case GL_LUMINANCE32F_EXT:
9948 case GL_LUMINANCE_ALPHA32F_EXT:
9950 case GL_RGBA16F_EXT:
9951 return GL_HALF_FLOAT_OES;
9953 return GL_HALF_FLOAT_OES;
9954 case GL_ALPHA16F_EXT:
9955 return GL_HALF_FLOAT_OES;
9956 case GL_LUMINANCE16F_EXT:
9957 return GL_HALF_FLOAT_OES;
9958 case GL_LUMINANCE_ALPHA16F_EXT:
9959 return GL_HALF_FLOAT_OES;
9961 return GL_UNSIGNED_BYTE;
9967 void GLES2DecoderImpl::DoTexStorage2DEXT(
9970 GLenum internal_format,
9973 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
9974 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
9975 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
9977 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
9980 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9984 GL_INVALID_OPERATION,
9985 "glTexStorage2DEXT", "unknown texture for target");
9988 Texture* texture = texture_ref->texture();
9989 if (texture->IsAttachedToFramebuffer()) {
9990 framebuffer_state_.clear_state_dirty = true;
9992 if (texture->IsImmutable()) {
9994 GL_INVALID_OPERATION,
9995 "glTexStorage2DEXT", "texture is immutable");
9999 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10000 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10003 GLsizei level_width = width;
10004 GLsizei level_height = height;
10005 uint32 estimated_size = 0;
10006 for (int ii = 0; ii < levels; ++ii) {
10007 uint32 level_size = 0;
10008 if (!GLES2Util::ComputeImageDataSizes(
10009 level_width, level_height, format, type, state_.unpack_alignment,
10010 &estimated_size, NULL, NULL) ||
10011 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10012 LOCAL_SET_GL_ERROR(
10013 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10016 level_width = std::max(1, level_width >> 1);
10017 level_height = std::max(1, level_height >> 1);
10019 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10020 LOCAL_SET_GL_ERROR(
10021 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10026 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10027 glTexStorage2DEXT(target, levels, internal_format, width, height);
10028 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10029 if (error == GL_NO_ERROR) {
10030 GLsizei level_width = width;
10031 GLsizei level_height = height;
10032 for (int ii = 0; ii < levels; ++ii) {
10033 texture_manager()->SetLevelInfo(
10034 texture_ref, target, ii, format,
10035 level_width, level_height, 1, 0, format, type, false);
10036 level_width = std::max(1, level_width >> 1);
10037 level_height = std::max(1, level_height >> 1);
10039 texture->SetImmutable(true);
10043 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10044 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
10045 return error::kUnknownCommand;
10048 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10049 const GLbyte* data) {
10050 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10051 "context", logger_.GetLogPrefix(),
10052 "mailbox[0]", static_cast<unsigned char>(data[0]));
10054 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10055 DLOG_IF(ERROR, !mailbox.Verify()) << "ProduceTextureCHROMIUM was passed a "
10056 "mailbox that was not generated by "
10057 "GenMailboxCHROMIUM.";
10059 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10061 if (!texture_ref) {
10062 LOCAL_SET_GL_ERROR(
10063 GL_INVALID_OPERATION,
10064 "glProduceTextureCHROMIUM", "unknown texture for target");
10068 Texture* produced = texture_manager()->Produce(texture_ref);
10070 LOCAL_SET_GL_ERROR(
10071 GL_INVALID_OPERATION,
10072 "glProduceTextureCHROMIUM", "invalid texture");
10076 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10079 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10080 const GLbyte* data) {
10081 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10082 "context", logger_.GetLogPrefix(),
10083 "mailbox[0]", static_cast<unsigned char>(data[0]));
10084 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10085 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10086 "mailbox that was not generated by "
10087 "GenMailboxCHROMIUM.";
10089 scoped_refptr<TextureRef> texture_ref =
10090 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10091 if (!texture_ref.get()) {
10092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10093 "glConsumeTextureCHROMIUM",
10094 "unknown texture for target");
10097 GLuint client_id = texture_ref->client_id();
10099 LOCAL_SET_GL_ERROR(
10100 GL_INVALID_OPERATION,
10101 "glConsumeTextureCHROMIUM", "unknown texture for target");
10104 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10106 LOCAL_SET_GL_ERROR(
10107 GL_INVALID_OPERATION,
10108 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10111 if (texture->target() != target) {
10112 LOCAL_SET_GL_ERROR(
10113 GL_INVALID_OPERATION,
10114 "glConsumeTextureCHROMIUM", "invalid target");
10118 DeleteTexturesHelper(1, &client_id);
10119 texture_ref = texture_manager()->Consume(client_id, texture);
10120 glBindTexture(target, texture_ref->service_id());
10122 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10123 unit.bind_target = target;
10125 case GL_TEXTURE_2D:
10126 unit.bound_texture_2d = texture_ref;
10128 case GL_TEXTURE_CUBE_MAP:
10129 unit.bound_texture_cube_map = texture_ref;
10131 case GL_TEXTURE_EXTERNAL_OES:
10132 unit.bound_texture_external_oes = texture_ref;
10134 case GL_TEXTURE_RECTANGLE_ARB:
10135 unit.bound_texture_rectangle_arb = texture_ref;
10138 NOTREACHED(); // Validation should prevent us getting here.
10143 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10144 GLsizei length, const GLchar* marker) {
10148 debug_marker_manager_.SetMarker(
10149 length ? std::string(marker, length) : std::string(marker));
10152 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10153 GLsizei length, const GLchar* marker) {
10157 std::string name = length ? std::string(marker, length) : std::string(marker);
10158 debug_marker_manager_.PushGroup(name);
10159 gpu_tracer_->Begin(name, kTraceGroupMarker);
10162 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10163 debug_marker_manager_.PopGroup();
10164 gpu_tracer_->End(kTraceGroupMarker);
10167 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10168 GLenum target, GLint image_id) {
10169 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10171 if (target == GL_TEXTURE_CUBE_MAP) {
10172 LOCAL_SET_GL_ERROR(
10174 "glBindTexImage2DCHROMIUM", "invalid target");
10178 // Default target might be conceptually valid, but disallow it to avoid
10180 TextureRef* texture_ref =
10181 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10182 if (!texture_ref) {
10183 LOCAL_SET_GL_ERROR(
10184 GL_INVALID_OPERATION,
10185 "glBindTexImage2DCHROMIUM", "no texture bound");
10189 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10191 LOCAL_SET_GL_ERROR(
10192 GL_INVALID_OPERATION,
10193 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10198 ScopedGLErrorSuppressor suppressor(
10199 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10200 if (!gl_image->BindTexImage(target)) {
10201 LOCAL_SET_GL_ERROR(
10202 GL_INVALID_OPERATION,
10203 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10208 gfx::Size size = gl_image->GetSize();
10209 texture_manager()->SetLevelInfo(
10210 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10211 GL_RGBA, GL_UNSIGNED_BYTE, true);
10212 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10215 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10216 GLenum target, GLint image_id) {
10217 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10219 // Default target might be conceptually valid, but disallow it to avoid
10221 TextureRef* texture_ref =
10222 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10223 if (!texture_ref) {
10224 LOCAL_SET_GL_ERROR(
10225 GL_INVALID_OPERATION,
10226 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10230 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10232 LOCAL_SET_GL_ERROR(
10233 GL_INVALID_OPERATION,
10234 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10238 // Do nothing when image is not currently bound.
10239 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10243 ScopedGLErrorSuppressor suppressor(
10244 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10245 gl_image->ReleaseTexImage(target);
10248 texture_manager()->SetLevelInfo(
10249 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10250 GL_RGBA, GL_UNSIGNED_BYTE, false);
10253 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10254 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10255 Bucket* bucket = GetBucket(c.bucket_id);
10256 if (!bucket || bucket->size() == 0) {
10257 return error::kInvalidArguments;
10259 std::string command_name;
10260 if (!bucket->GetAsString(&command_name)) {
10261 return error::kInvalidArguments;
10263 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10264 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10265 LOCAL_SET_GL_ERROR(
10266 GL_INVALID_OPERATION,
10267 "glTraceBeginCHROMIUM", "unable to create begin trace");
10268 return error::kNoError;
10270 return error::kNoError;
10273 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10274 if (gpu_tracer_->CurrentName().empty()) {
10275 LOCAL_SET_GL_ERROR(
10276 GL_INVALID_OPERATION,
10277 "glTraceEndCHROMIUM", "no trace begin found");
10280 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10281 gpu_tracer_->End(kTraceCHROMIUM);
10284 void GLES2DecoderImpl::DoDrawBuffersEXT(
10285 GLsizei count, const GLenum* bufs) {
10286 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10287 LOCAL_SET_GL_ERROR(
10289 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10293 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10295 for (GLsizei i = 0; i < count; ++i) {
10296 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10297 bufs[i] != GL_NONE) {
10298 LOCAL_SET_GL_ERROR(
10299 GL_INVALID_OPERATION,
10300 "glDrawBuffersEXT",
10301 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10305 glDrawBuffersARB(count, bufs);
10306 framebuffer->SetDrawBuffers(count, bufs);
10307 } else { // backbuffer
10309 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10310 LOCAL_SET_GL_ERROR(
10311 GL_INVALID_OPERATION,
10312 "glDrawBuffersEXT",
10313 "more than one buffer or bufs not GL_NONE or GL_BACK");
10316 GLenum mapped_buf = bufs[0];
10317 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10318 bufs[0] == GL_BACK) {
10319 mapped_buf = GL_COLOR_ATTACHMENT0;
10321 glDrawBuffersARB(count, &mapped_buf);
10322 group_->set_draw_buffer(bufs[0]);
10326 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10327 const char* function_name,
10328 TextureRef* texture_ref,
10331 const void * data) {
10332 // We only support async uploads to 2D textures for now.
10333 if (GL_TEXTURE_2D != target) {
10334 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10337 // We only support uploads to level zero for now.
10339 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10342 // A transfer buffer must be bound, even for asyncTexImage2D.
10343 if (data == NULL) {
10344 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10347 // We only support one async transfer in progress.
10348 if (!texture_ref ||
10349 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10350 LOCAL_SET_GL_ERROR(
10351 GL_INVALID_OPERATION,
10352 function_name, "transfer already in progress");
10358 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10359 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10360 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10361 GLenum target = static_cast<GLenum>(c.target);
10362 GLint level = static_cast<GLint>(c.level);
10363 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10364 // unsigned integer for internalformat.
10365 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10366 GLsizei width = static_cast<GLsizei>(c.width);
10367 GLsizei height = static_cast<GLsizei>(c.height);
10368 GLint border = static_cast<GLint>(c.border);
10369 GLenum format = static_cast<GLenum>(c.format);
10370 GLenum type = static_cast<GLenum>(c.type);
10371 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10372 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10373 uint32 pixels_size;
10375 // TODO(epenner): Move this and copies of this memory validation
10376 // into ValidateTexImage2D step.
10377 if (!GLES2Util::ComputeImageDataSizes(
10378 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10380 return error::kOutOfBounds;
10382 const void* pixels = NULL;
10383 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10384 pixels = GetSharedMemoryAs<const void*>(
10385 pixels_shm_id, pixels_shm_offset, pixels_size);
10387 return error::kOutOfBounds;
10391 TextureManager::DoTextImage2DArguments args = {
10392 target, level, internal_format, width, height, border, format, type,
10393 pixels, pixels_size};
10394 TextureRef* texture_ref;
10395 // All the normal glTexSubImage2D validation.
10396 if (!texture_manager()->ValidateTexImage2D(
10397 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10398 return error::kNoError;
10401 // Extra async validation.
10402 Texture* texture = texture_ref->texture();
10403 if (!ValidateAsyncTransfer(
10404 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10405 return error::kNoError;
10407 // Don't allow async redefinition of a textures.
10408 if (texture->IsDefined()) {
10409 LOCAL_SET_GL_ERROR(
10410 GL_INVALID_OPERATION,
10411 "glAsyncTexImage2DCHROMIUM", "already defined");
10412 return error::kNoError;
10415 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10416 LOCAL_SET_GL_ERROR(
10417 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10418 return error::kNoError;
10421 // Setup the parameters.
10422 AsyncTexImage2DParams tex_params = {
10423 target, level, static_cast<GLenum>(internal_format),
10424 width, height, border, format, type};
10425 AsyncMemoryParams mem_params(
10426 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
10428 // Set up the async state if needed, and make the texture
10429 // immutable so the async state stays valid. The level info
10430 // is set up lazily when the transfer completes.
10431 AsyncPixelTransferDelegate* delegate =
10432 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10434 texture->SetImmutable(true);
10436 delegate->AsyncTexImage2D(
10439 base::Bind(&TextureManager::SetLevelInfoFromParams,
10440 // The callback is only invoked if the transfer delegate still
10441 // exists, which implies through manager->texture_ref->state
10442 // ownership that both of these pointers are valid.
10443 base::Unretained(texture_manager()),
10444 base::Unretained(texture_ref),
10446 return error::kNoError;
10449 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10450 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10451 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10452 GLenum target = static_cast<GLenum>(c.target);
10453 GLint level = static_cast<GLint>(c.level);
10454 GLint xoffset = static_cast<GLint>(c.xoffset);
10455 GLint yoffset = static_cast<GLint>(c.yoffset);
10456 GLsizei width = static_cast<GLsizei>(c.width);
10457 GLsizei height = static_cast<GLsizei>(c.height);
10458 GLenum format = static_cast<GLenum>(c.format);
10459 GLenum type = static_cast<GLenum>(c.type);
10461 // TODO(epenner): Move this and copies of this memory validation
10462 // into ValidateTexSubImage2D step.
10464 if (!GLES2Util::ComputeImageDataSizes(
10465 width, height, format, type, state_.unpack_alignment, &data_size,
10467 return error::kOutOfBounds;
10469 const void* pixels = GetSharedMemoryAs<const void*>(
10470 c.data_shm_id, c.data_shm_offset, data_size);
10472 // All the normal glTexSubImage2D validation.
10473 error::Error error = error::kNoError;
10474 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10475 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10479 // Extra async validation.
10480 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10482 Texture* texture = texture_ref->texture();
10483 if (!ValidateAsyncTransfer(
10484 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10485 return error::kNoError;
10487 // Guarantee async textures are always 'cleared' as follows:
10488 // - AsyncTexImage2D can not redefine an existing texture
10489 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10490 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10491 // - Textures become immutable after an async call.
10492 // This way we know in all cases that an async texture is always clear.
10493 if (!texture->SafeToRenderFrom()) {
10494 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10496 LOCAL_SET_GL_ERROR(
10498 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10499 return error::kNoError;
10503 // Setup the parameters.
10504 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10505 width, height, format, type};
10506 AsyncMemoryParams mem_params(
10507 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
10508 AsyncPixelTransferDelegate* delegate =
10509 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10511 // TODO(epenner): We may want to enforce exclusive use
10512 // of async APIs in which case this should become an error,
10513 // (the texture should have been async defined).
10514 AsyncTexImage2DParams define_params = {target, level,
10516 texture->GetLevelSize(target, level, &define_params.width,
10517 &define_params.height);
10518 texture->GetLevelType(target, level, &define_params.type,
10519 &define_params.internal_format);
10520 // Set up the async state if needed, and make the texture
10521 // immutable so the async state stays valid.
10522 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10523 texture_ref, define_params);
10524 texture->SetImmutable(true);
10527 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10528 return error::kNoError;
10531 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10532 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10533 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10534 GLenum target = static_cast<GLenum>(c.target);
10536 if (GL_TEXTURE_2D != target) {
10537 LOCAL_SET_GL_ERROR(
10538 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10539 return error::kNoError;
10541 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10543 if (!texture_ref) {
10544 LOCAL_SET_GL_ERROR(
10545 GL_INVALID_OPERATION,
10546 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10547 return error::kNoError;
10549 AsyncPixelTransferDelegate* delegate =
10550 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10552 LOCAL_SET_GL_ERROR(
10553 GL_INVALID_OPERATION,
10554 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10555 return error::kNoError;
10557 delegate->WaitForTransferCompletion();
10558 ProcessFinishedAsyncTransfers();
10559 return error::kNoError;
10562 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10563 TextureRef* texture_ref) {
10564 Texture* texture = texture_ref->texture();
10565 DoDidUseTexImageIfNeeded(texture, texture->target());
10568 // Include the auto-generated part of this file. We split this because it means
10569 // we can easily edit the non-auto generated parts right here in this file
10570 // instead of having to edit some template or the code generator.
10571 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10573 } // namespace gles2