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 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 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 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 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 // Encapsulates an OpenGL texture.
360 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
363 // Create a new render texture.
366 // Set the initial size and format of a render texture or resize it.
367 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
369 // Copy the contents of the currently bound frame buffer.
370 void Copy(const gfx::Size& size, GLenum format);
372 // Destroy the render texture. This must be explicitly called before
373 // destroying this object.
376 // Invalidate the texture. This can be used when a context is lost and it is
377 // not possible to make it current in order to free the resource.
384 gfx::Size size() const {
389 MemoryTypeTracker memory_tracker_;
390 ContextState* state_;
391 size_t bytes_allocated_;
394 DISALLOW_COPY_AND_ASSIGN(BackTexture);
397 // Encapsulates an OpenGL render buffer of any format.
398 class BackRenderbuffer {
400 explicit BackRenderbuffer(
401 RenderbufferManager* renderbuffer_manager,
402 MemoryTracker* memory_tracker,
403 ContextState* state);
406 // Create a new render buffer.
409 // Set the initial size and format of a render buffer or resize it.
410 bool AllocateStorage(const FeatureInfo* feature_info,
411 const gfx::Size& size,
415 // Destroy the render buffer. This must be explicitly called before destroying
419 // Invalidate the render buffer. This can be used when a context is lost and
420 // it is not possible to make it current in order to free the resource.
428 RenderbufferManager* renderbuffer_manager_;
429 MemoryTypeTracker memory_tracker_;
430 ContextState* state_;
431 size_t bytes_allocated_;
433 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
436 // Encapsulates an OpenGL frame buffer.
437 class BackFramebuffer {
439 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
442 // Create a new frame buffer.
445 // Attach a color render buffer to a frame buffer.
446 void AttachRenderTexture(BackTexture* texture);
448 // Attach a render buffer to a frame buffer. Note that this unbinds any
449 // currently bound frame buffer.
450 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
452 // Destroy the frame buffer. This must be explicitly called before destroying
456 // Invalidate the frame buffer. This can be used when a context is lost and it
457 // is not possible to make it current in order to free the resource.
460 // See glCheckFramebufferStatusEXT.
461 GLenum CheckStatus();
468 GLES2DecoderImpl* decoder_;
470 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
473 struct FenceCallback {
474 explicit FenceCallback()
475 : fence(gfx::GLFence::Create()) {
478 std::vector<base::Closure> callbacks;
479 scoped_ptr<gfx::GLFence> fence;
482 // } // anonymous namespace.
484 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
485 uint32* service_texture_id) {
489 GLES2Decoder::GLES2Decoder()
490 : initialized_(false),
492 log_commands_(false) {
495 GLES2Decoder::~GLES2Decoder() {
498 void GLES2Decoder::BeginDecoding() {}
500 void GLES2Decoder::EndDecoding() {}
502 // This class implements GLES2Decoder so we don't have to expose all the GLES2
503 // cmd stuff to outside this class.
504 class GLES2DecoderImpl : public GLES2Decoder,
505 public FramebufferManager::TextureDetachObserver {
507 // Used by PrepForSetUniformByLocation to validate types.
508 struct BaseUniformInfo {
509 const GLenum* const valid_types;
510 size_t num_valid_types;
513 explicit GLES2DecoderImpl(ContextGroup* group);
514 virtual ~GLES2DecoderImpl();
516 // Overridden from AsyncAPIInterface.
517 virtual Error DoCommand(unsigned int command,
518 unsigned int arg_count,
519 const void* args) OVERRIDE;
521 // Overridden from AsyncAPIInterface.
522 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
524 // Overridden from GLES2Decoder.
525 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
526 const scoped_refptr<gfx::GLContext>& context,
528 const gfx::Size& size,
529 const DisallowedFeatures& disallowed_features,
530 const std::vector<int32>& attribs) OVERRIDE;
531 virtual void Destroy(bool have_context) OVERRIDE;
532 virtual void SetSurface(
533 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
534 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
535 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
536 void UpdateParentTextureInfo();
537 virtual bool MakeCurrent() OVERRIDE;
538 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
539 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
540 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
541 virtual Capabilities GetCapabilities() OVERRIDE;
542 virtual void RestoreState(const ContextState* prev_state) const OVERRIDE;
544 virtual void RestoreActiveTexture() const OVERRIDE {
545 state_.RestoreActiveTexture();
547 virtual void RestoreAllTextureUnitBindings(
548 const ContextState* prev_state) const OVERRIDE {
549 state_.RestoreAllTextureUnitBindings(prev_state);
551 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
552 state_.RestoreAttribute(index);
554 virtual void RestoreBufferBindings() const OVERRIDE {
555 state_.RestoreBufferBindings();
557 virtual void RestoreGlobalState() const OVERRIDE {
558 state_.RestoreGlobalState();
560 virtual void RestoreProgramBindings() const OVERRIDE {
561 state_.RestoreProgramBindings();
563 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
564 state_.RestoreTextureUnitBindings(unit, NULL);
566 virtual void RestoreFramebufferBindings() const OVERRIDE;
567 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
569 virtual void ClearAllAttributes() const OVERRIDE;
570 virtual void RestoreAllAttributes() const OVERRIDE;
572 virtual QueryManager* GetQueryManager() OVERRIDE {
573 return query_manager_.get();
575 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
576 return vertex_array_manager_.get();
578 virtual bool ProcessPendingQueries() OVERRIDE;
579 virtual bool HasMoreIdleWork() OVERRIDE;
580 virtual void PerformIdleWork() OVERRIDE;
582 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
584 virtual void SetResizeCallback(
585 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
587 virtual Logger* GetLogger() OVERRIDE;
589 virtual void BeginDecoding() OVERRIDE;
590 virtual void EndDecoding() OVERRIDE;
592 virtual ErrorState* GetErrorState() OVERRIDE;
593 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
595 virtual void SetShaderCacheCallback(
596 const ShaderCacheCallback& callback) OVERRIDE;
597 virtual void SetWaitSyncPointCallback(
598 const WaitSyncPointCallback& callback) OVERRIDE;
600 virtual AsyncPixelTransferManager*
601 GetAsyncPixelTransferManager() OVERRIDE;
602 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
603 virtual void SetAsyncPixelTransferManagerForTest(
604 AsyncPixelTransferManager* manager) OVERRIDE;
605 void ProcessFinishedAsyncTransfers();
607 virtual bool GetServiceTextureId(uint32 client_texture_id,
608 uint32* service_texture_id) OVERRIDE;
610 virtual uint32 GetTextureUploadCount() OVERRIDE;
611 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
612 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
613 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
615 // Restores the current state to the user's settings.
616 void RestoreCurrentFramebufferBindings();
618 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
619 void ApplyDirtyState();
621 // These check the state of the currently bound framebuffer or the
622 // backbuffer if no framebuffer is bound.
623 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
624 // check with all attached and enabled color attachments.
625 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
626 bool BoundFramebufferHasDepthAttachment();
627 bool BoundFramebufferHasStencilAttachment();
629 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
631 // Overridden from FramebufferManager::TextureDetachObserver:
632 virtual void OnTextureRefDetachedFromFramebuffer(
633 TextureRef* texture) OVERRIDE;
635 // Helpers to facilitate calling into compatible extensions.
636 static void RenderbufferStorageMultisampleHelper(
637 const FeatureInfo* feature_info,
640 GLenum internal_format,
644 void BlitFramebufferHelper(GLint srcX0,
656 friend class ScopedFrameBufferBinder;
657 friend class ScopedResolvedFrameBufferBinder;
658 friend class BackFramebuffer;
660 // Initialize or re-initialize the shader translator.
661 bool InitializeShaderTranslator();
663 void UpdateCapabilities();
665 // Helpers for the glGen and glDelete functions.
666 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
667 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
668 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
669 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
670 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
671 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
672 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
673 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
674 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
675 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
676 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
677 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
680 void OnFboChanged() const;
681 void OnUseFramebuffer() const;
683 // TODO(gman): Cache these pointers?
684 BufferManager* buffer_manager() {
685 return group_->buffer_manager();
688 RenderbufferManager* renderbuffer_manager() {
689 return group_->renderbuffer_manager();
692 FramebufferManager* framebuffer_manager() {
693 return group_->framebuffer_manager();
696 ProgramManager* program_manager() {
697 return group_->program_manager();
700 ShaderManager* shader_manager() {
701 return group_->shader_manager();
704 const TextureManager* texture_manager() const {
705 return group_->texture_manager();
708 TextureManager* texture_manager() {
709 return group_->texture_manager();
712 MailboxManager* mailbox_manager() {
713 return group_->mailbox_manager();
716 ImageManager* image_manager() {
717 return group_->image_manager();
720 VertexArrayManager* vertex_array_manager() {
721 return vertex_array_manager_.get();
724 MemoryTracker* memory_tracker() {
725 return group_->memory_tracker();
728 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
729 MemoryTracker* tracker = memory_tracker();
731 return tracker->EnsureGPUMemoryAvailable(estimated_size);
736 bool IsOffscreenBufferMultisampled() const {
737 return offscreen_target_samples_ > 1;
740 // Creates a Texture for the given texture.
741 TextureRef* CreateTexture(
742 GLuint client_id, GLuint service_id) {
743 return texture_manager()->CreateTexture(client_id, service_id);
746 // Gets the texture info for the given texture. Returns NULL if none exists.
747 TextureRef* GetTexture(GLuint client_id) const {
748 return texture_manager()->GetTexture(client_id);
751 // Deletes the texture info for the given texture.
752 void RemoveTexture(GLuint client_id) {
753 texture_manager()->RemoveTexture(client_id);
756 // Get the size (in pixels) of the currently bound frame buffer (either FBO
757 // or regular back buffer).
758 gfx::Size GetBoundReadFrameBufferSize();
760 // Get the format of the currently bound frame buffer (either FBO or regular
762 GLenum GetBoundReadFrameBufferTextureType();
763 GLenum GetBoundReadFrameBufferInternalFormat();
764 GLenum GetBoundDrawFrameBufferInternalFormat();
766 // Wrapper for CompressedTexImage2D commands.
767 error::Error DoCompressedTexImage2D(
770 GLenum internal_format,
777 // Wrapper for CompressedTexSubImage2D.
778 void DoCompressedTexSubImage2D(
789 // Wrapper for CopyTexImage2D.
790 void DoCopyTexImage2D(
793 GLenum internal_format,
800 // Wrapper for SwapBuffers.
801 void DoSwapBuffers();
803 // Wrapper for CopyTexSubImage2D.
804 void DoCopyTexSubImage2D(
814 // Validation for TexSubImage2D.
815 bool ValidateTexSubImage2D(
817 const char* function_name,
828 // Wrapper for TexSubImage2D.
829 error::Error DoTexSubImage2D(
840 // Extra validation for async tex(Sub)Image2D.
841 bool ValidateAsyncTransfer(
842 const char* function_name,
843 TextureRef* texture_ref,
848 // Wrapper for TexImageIOSurface2DCHROMIUM.
849 void DoTexImageIOSurface2DCHROMIUM(
853 GLuint io_surface_id,
856 void DoCopyTextureCHROMIUM(
861 GLenum internal_format,
864 // Wrapper for TexStorage2DEXT.
865 void DoTexStorage2DEXT(
868 GLenum internal_format,
872 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
873 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
875 void DoBindTexImage2DCHROMIUM(
878 void DoReleaseTexImage2DCHROMIUM(
882 void DoTraceEndCHROMIUM(void);
884 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
886 // Creates a Program for the given program.
887 Program* CreateProgram(
888 GLuint client_id, GLuint service_id) {
889 return program_manager()->CreateProgram(client_id, service_id);
892 // Gets the program info for the given program. Returns NULL if none exists.
893 Program* GetProgram(GLuint client_id) {
894 return program_manager()->GetProgram(client_id);
898 void LogClientServiceMapping(
899 const char* /* function_name */,
900 GLuint /* client_id */,
901 GLuint /* service_id */) {
904 void LogClientServiceForInfo(
905 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
908 void LogClientServiceMapping(
909 const char* function_name, GLuint client_id, GLuint service_id) {
910 if (service_logging_) {
911 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
912 << ": client_id = " << client_id
913 << ", service_id = " << service_id;
917 void LogClientServiceForInfo(
918 T* info, GLuint client_id, const char* function_name) {
920 LogClientServiceMapping(function_name, client_id, info->service_id());
925 // Gets the program info for the given program. If it's not a program
926 // generates a GL error. Returns NULL if not program.
927 Program* GetProgramInfoNotShader(
928 GLuint client_id, const char* function_name) {
929 Program* program = GetProgram(client_id);
931 if (GetShader(client_id)) {
933 GL_INVALID_OPERATION, function_name, "shader passed for program");
935 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
938 LogClientServiceForInfo(program, client_id, function_name);
943 // Creates a Shader for the given shader.
944 Shader* CreateShader(
947 GLenum shader_type) {
948 return shader_manager()->CreateShader(
949 client_id, service_id, shader_type);
952 // Gets the shader info for the given shader. Returns NULL if none exists.
953 Shader* GetShader(GLuint client_id) {
954 return shader_manager()->GetShader(client_id);
957 // Gets the shader info for the given shader. If it's not a shader generates a
958 // GL error. Returns NULL if not shader.
959 Shader* GetShaderInfoNotProgram(
960 GLuint client_id, const char* function_name) {
961 Shader* shader = GetShader(client_id);
963 if (GetProgram(client_id)) {
965 GL_INVALID_OPERATION, function_name, "program passed for shader");
968 GL_INVALID_VALUE, function_name, "unknown shader");
971 LogClientServiceForInfo(shader, client_id, function_name);
975 // Creates a buffer info for the given buffer.
976 void CreateBuffer(GLuint client_id, GLuint service_id) {
977 return buffer_manager()->CreateBuffer(client_id, service_id);
980 // Gets the buffer info for the given buffer.
981 Buffer* GetBuffer(GLuint client_id) {
982 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
986 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
987 // on glDeleteBuffers so we can make sure the user does not try to render
988 // with deleted buffers.
989 void RemoveBuffer(GLuint client_id);
991 // Creates a framebuffer info for the given framebuffer.
992 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
993 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
996 // Gets the framebuffer info for the given framebuffer.
997 Framebuffer* GetFramebuffer(GLuint client_id) {
998 return framebuffer_manager()->GetFramebuffer(client_id);
1001 // Removes the framebuffer info for the given framebuffer.
1002 void RemoveFramebuffer(GLuint client_id) {
1003 framebuffer_manager()->RemoveFramebuffer(client_id);
1006 // Creates a renderbuffer info for the given renderbuffer.
1007 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1008 return renderbuffer_manager()->CreateRenderbuffer(
1009 client_id, service_id);
1012 // Gets the renderbuffer info for the given renderbuffer.
1013 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1014 return renderbuffer_manager()->GetRenderbuffer(client_id);
1017 // Removes the renderbuffer info for the given renderbuffer.
1018 void RemoveRenderbuffer(GLuint client_id) {
1019 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1022 // Gets the vertex attrib manager for the given vertex array.
1023 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1024 VertexAttribManager* info =
1025 vertex_array_manager()->GetVertexAttribManager(client_id);
1029 // Removes the vertex attrib manager for the given vertex array.
1030 void RemoveVertexAttribManager(GLuint client_id) {
1031 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1034 // Creates a vertex attrib manager for the given vertex array.
1035 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1036 return vertex_array_manager()->CreateVertexAttribManager(
1037 client_id, service_id, group_->max_vertex_attribs());
1040 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1041 void DoBindUniformLocationCHROMIUM(
1042 GLuint client_id, GLint location, const char* name);
1044 error::Error GetAttribLocationHelper(
1045 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1046 const std::string& name_str);
1048 error::Error GetUniformLocationHelper(
1049 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1050 const std::string& name_str);
1052 // Helper for glShaderSource.
1053 error::Error ShaderSourceHelper(
1054 GLuint client_id, const char* data, uint32 data_size);
1056 // Clear any textures used by the current program.
1057 bool ClearUnclearedTextures();
1059 // Clears any uncleared attachments attached to the given frame buffer.
1060 // Returns false if there was a generated GL error.
1061 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1063 // overridden from GLES2Decoder
1064 virtual bool ClearLevel(unsigned service_id,
1065 unsigned bind_target,
1072 bool is_texture_immutable) OVERRIDE;
1074 // Restore all GL state that affects clearing.
1075 void RestoreClearState();
1077 // Remembers the state of some capabilities.
1078 // Returns: true if glEnable/glDisable should actually be called.
1079 bool SetCapabilityState(GLenum cap, bool enabled);
1081 // Check that the currently bound framebuffers are valid.
1082 // Generates GL error if not.
1083 bool CheckBoundFramebuffersValid(const char* func_name);
1085 // Check if a framebuffer meets our requirements.
1086 bool CheckFramebufferValid(
1087 Framebuffer* framebuffer,
1089 const char* func_name);
1091 // Checks if the current program exists and is valid. If not generates the
1092 // appropriate GL error. Returns true if the current program is in a usable
1094 bool CheckCurrentProgram(const char* function_name);
1096 // Checks if the current program exists and is valid and that location is not
1097 // -1. If the current program is not valid generates the appropriate GL
1098 // error. Returns true if the current program is in a usable state and
1099 // location is not -1.
1100 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1102 // Gets the type of a uniform for a location in the current program. Sets GL
1103 // errors if the current program is not valid. Returns true if the current
1104 // program is valid and the location exists. Adjusts count so it
1105 // does not overflow the uniform.
1106 bool PrepForSetUniformByLocation(
1107 GLint fake_location, const char* function_name,
1108 const BaseUniformInfo& base_info,
1109 GLint* real_location, GLenum* type, GLsizei* count);
1111 // Gets the service id for any simulated backbuffer fbo.
1112 GLuint GetBackbufferServiceId() const;
1114 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1115 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1117 // Helper for glGetVertexAttrib
1118 void GetVertexAttribHelper(
1119 const VertexAttrib* attrib, GLenum pname, GLint* param);
1121 // Wrapper for glCreateProgram
1122 bool CreateProgramHelper(GLuint client_id);
1124 // Wrapper for glCreateShader
1125 bool CreateShaderHelper(GLenum type, GLuint client_id);
1127 // Wrapper for glActiveTexture
1128 void DoActiveTexture(GLenum texture_unit);
1130 // Wrapper for glAttachShader
1131 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1133 // Wrapper for glBindBuffer since we need to track the current targets.
1134 void DoBindBuffer(GLenum target, GLuint buffer);
1136 // Wrapper for glBindFramebuffer since we need to track the current targets.
1137 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1139 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1140 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1142 // Wrapper for glBindTexture since we need to track the current targets.
1143 void DoBindTexture(GLenum target, GLuint texture);
1145 // Wrapper for glBindVertexArrayOES
1146 void DoBindVertexArrayOES(GLuint array);
1147 void EmulateVertexArrayState();
1149 // Wrapper for glBlitFramebufferCHROMIUM.
1150 void DoBlitFramebufferCHROMIUM(
1151 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1152 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1153 GLbitfield mask, GLenum filter);
1155 // Wrapper for glBufferSubData.
1156 void DoBufferSubData(
1157 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1159 // Wrapper for glCheckFramebufferStatus
1160 GLenum DoCheckFramebufferStatus(GLenum target);
1162 // Wrapper for glClear
1163 error::Error DoClear(GLbitfield mask);
1165 // Wrappers for various state.
1166 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1167 void DoSampleCoverage(GLclampf value, GLboolean invert);
1169 // Wrapper for glCompileShader.
1170 void DoCompileShader(GLuint shader);
1172 // Helper for DeleteSharedIdsCHROMIUM commands.
1173 void DoDeleteSharedIdsCHROMIUM(
1174 GLuint namespace_id, GLsizei n, const GLuint* ids);
1176 // Wrapper for glDetachShader
1177 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1179 // Wrapper for glDisable
1180 void DoDisable(GLenum cap);
1182 // Wrapper for glDisableVertexAttribArray.
1183 void DoDisableVertexAttribArray(GLuint index);
1185 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1187 void DoDiscardFramebufferEXT(GLenum target,
1188 GLsizei numAttachments,
1189 const GLenum* attachments);
1191 // Wrapper for glEnable
1192 void DoEnable(GLenum cap);
1194 // Wrapper for glEnableVertexAttribArray.
1195 void DoEnableVertexAttribArray(GLuint index);
1197 // Wrapper for glFinish.
1200 // Wrapper for glFlush.
1203 // Wrapper for glFramebufferRenderbufffer.
1204 void DoFramebufferRenderbuffer(
1205 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1206 GLuint renderbuffer);
1208 // Wrapper for glFramebufferTexture2D.
1209 void DoFramebufferTexture2D(
1210 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1213 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1214 void DoFramebufferTexture2DMultisample(
1215 GLenum target, GLenum attachment, GLenum textarget,
1216 GLuint texture, GLint level, GLsizei samples);
1218 // Common implementation for both DoFramebufferTexture2D wrappers.
1219 void DoFramebufferTexture2DCommon(const char* name,
1220 GLenum target, GLenum attachment, GLenum textarget,
1221 GLuint texture, GLint level, GLsizei samples);
1223 // Wrapper for glGenerateMipmap
1224 void DoGenerateMipmap(GLenum target);
1226 // Helper for GenSharedIdsCHROMIUM commands.
1227 void DoGenSharedIdsCHROMIUM(
1228 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1230 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1231 // to account for different pname values defined in different extension
1233 GLenum AdjustGetPname(GLenum pname);
1235 // Wrapper for DoGetBooleanv.
1236 void DoGetBooleanv(GLenum pname, GLboolean* params);
1238 // Wrapper for DoGetFloatv.
1239 void DoGetFloatv(GLenum pname, GLfloat* params);
1241 // Wrapper for glGetFramebufferAttachmentParameteriv.
1242 void DoGetFramebufferAttachmentParameteriv(
1243 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1245 // Wrapper for glGetIntegerv.
1246 void DoGetIntegerv(GLenum pname, GLint* params);
1248 // Gets the max value in a range in a buffer.
1249 GLuint DoGetMaxValueInBufferCHROMIUM(
1250 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1252 // Wrapper for glGetBufferParameteriv.
1253 void DoGetBufferParameteriv(
1254 GLenum target, GLenum pname, GLint* params);
1256 // Wrapper for glGetProgramiv.
1257 void DoGetProgramiv(
1258 GLuint program_id, GLenum pname, GLint* params);
1260 // Wrapper for glRenderbufferParameteriv.
1261 void DoGetRenderbufferParameteriv(
1262 GLenum target, GLenum pname, GLint* params);
1264 // Wrapper for glGetShaderiv
1265 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1267 // Wrappers for glGetVertexAttrib.
1268 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1269 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1271 // Wrappers for glIsXXX functions.
1272 bool DoIsEnabled(GLenum cap);
1273 bool DoIsBuffer(GLuint client_id);
1274 bool DoIsFramebuffer(GLuint client_id);
1275 bool DoIsProgram(GLuint client_id);
1276 bool DoIsRenderbuffer(GLuint client_id);
1277 bool DoIsShader(GLuint client_id);
1278 bool DoIsTexture(GLuint client_id);
1279 bool DoIsVertexArrayOES(GLuint client_id);
1281 // Wrapper for glLinkProgram
1282 void DoLinkProgram(GLuint program);
1284 // Helper for RegisterSharedIdsCHROMIUM.
1285 void DoRegisterSharedIdsCHROMIUM(
1286 GLuint namespace_id, GLsizei n, const GLuint* ids);
1288 // Wrapper for glRenderbufferStorage.
1289 void DoRenderbufferStorage(
1290 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1292 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1293 void DoRenderbufferStorageMultisampleCHROMIUM(
1294 GLenum target, GLsizei samples, GLenum internalformat,
1295 GLsizei width, GLsizei height);
1297 // Handler for glRenderbufferStorageMultisampleEXT
1298 // (multisampled_render_to_texture).
1299 void DoRenderbufferStorageMultisampleEXT(
1300 GLenum target, GLsizei samples, GLenum internalformat,
1301 GLsizei width, GLsizei height);
1303 // Common validation for multisample extensions.
1304 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1305 GLenum internalformat,
1309 // Verifies that the currently bound multisample renderbuffer is valid
1310 // Very slow! Only done on platforms with driver bugs that return invalid
1311 // buffers under memory pressure
1312 bool VerifyMultisampleRenderbufferIntegrity(
1313 GLuint renderbuffer, GLenum format);
1315 // Wrapper for glReleaseShaderCompiler.
1316 void DoReleaseShaderCompiler() { }
1318 // Wrappers for glTexParameter functions.
1319 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1320 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1321 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1322 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1324 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1325 // spec only these 2 functions can be used to set sampler uniforms.
1326 void DoUniform1i(GLint fake_location, GLint v0);
1327 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1328 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1329 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1330 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1332 // Wrappers for glUniformfv because some drivers don't correctly accept
1334 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1335 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1336 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1337 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1339 void DoUniformMatrix2fv(
1340 GLint fake_location, GLsizei count, GLboolean transpose,
1341 const GLfloat* value);
1342 void DoUniformMatrix3fv(
1343 GLint fake_location, GLsizei count, GLboolean transpose,
1344 const GLfloat* value);
1345 void DoUniformMatrix4fv(
1346 GLint fake_location, GLsizei count, GLboolean transpose,
1347 const GLfloat* value);
1349 bool SetVertexAttribValue(
1350 const char* function_name, GLuint index, const GLfloat* value);
1352 // Wrappers for glVertexAttrib??
1353 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1354 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1355 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1356 void DoVertexAttrib4f(
1357 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1358 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1359 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1360 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1361 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1363 // Wrapper for glViewport
1364 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1366 // Wrapper for glUseProgram
1367 void DoUseProgram(GLuint program);
1369 // Wrapper for glValidateProgram.
1370 void DoValidateProgram(GLuint program_client_id);
1372 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1373 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1374 void DoPopGroupMarkerEXT(void);
1376 // Gets the number of values that will be returned by glGetXXX. Returns
1377 // false if pname is unknown.
1378 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1380 // Checks if the current program and vertex attributes are valid for drawing.
1382 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1384 // Returns true if successful, simulated will be true if attrib0 was
1386 bool SimulateAttrib0(
1387 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1388 void RestoreStateForAttrib(GLuint attrib);
1390 // If an image is bound to texture, this will call Will/DidUseTexImage
1392 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1393 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1395 // Returns false if textures were replaced.
1396 bool PrepareTexturesForRender();
1397 void RestoreStateForTextures();
1399 // Returns true if GL_FIXED attribs were simulated.
1400 bool SimulateFixedAttribs(
1401 const char* function_name,
1402 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1403 void RestoreStateForSimulatedFixedAttribs();
1405 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1406 // cases (primcount is 0 for non-instanced).
1407 error::Error DoDrawArrays(
1408 const char* function_name,
1409 bool instanced, GLenum mode, GLint first, GLsizei count,
1411 error::Error DoDrawElements(
1412 const char* function_name,
1413 bool instanced, GLenum mode, GLsizei count, GLenum type,
1414 int32 offset, GLsizei primcount);
1416 GLenum GetBindTargetForSamplerType(GLenum type) {
1417 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1418 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1421 return GL_TEXTURE_2D;
1422 case GL_SAMPLER_CUBE:
1423 return GL_TEXTURE_CUBE_MAP;
1424 case GL_SAMPLER_EXTERNAL_OES:
1425 return GL_TEXTURE_EXTERNAL_OES;
1426 case GL_SAMPLER_2D_RECT_ARB:
1427 return GL_TEXTURE_RECTANGLE_ARB;
1434 // Gets the framebuffer info for a particular target.
1435 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1436 Framebuffer* framebuffer = NULL;
1438 case GL_FRAMEBUFFER:
1439 case GL_DRAW_FRAMEBUFFER_EXT:
1440 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1442 case GL_READ_FRAMEBUFFER_EXT:
1443 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1452 Renderbuffer* GetRenderbufferInfoForTarget(
1454 Renderbuffer* renderbuffer = NULL;
1456 case GL_RENDERBUFFER:
1457 renderbuffer = state_.bound_renderbuffer.get();
1463 return renderbuffer;
1466 // Validates the program and location for a glGetUniform call and returns
1467 // a SizeResult setup to receive the result. Returns true if glGetUniform
1468 // should be called.
1469 bool GetUniformSetup(
1470 GLuint program, GLint fake_location,
1471 uint32 shm_id, uint32 shm_offset,
1472 error::Error* error, GLint* real_location, GLuint* service_id,
1473 void** result, GLenum* result_type);
1475 virtual bool WasContextLost() OVERRIDE;
1476 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1477 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1479 #if defined(OS_MACOSX)
1480 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1483 bool ValidateCompressedTexDimensions(
1484 const char* function_name,
1485 GLint level, GLsizei width, GLsizei height, GLenum format);
1486 bool ValidateCompressedTexFuncData(
1487 const char* function_name,
1488 GLsizei width, GLsizei height, GLenum format, size_t size);
1489 bool ValidateCompressedTexSubDimensions(
1490 const char* function_name,
1491 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1492 GLsizei width, GLsizei height, GLenum format,
1495 void RenderWarning(const char* filename, int line, const std::string& msg);
1496 void PerformanceWarning(
1497 const char* filename, int line, const std::string& msg);
1499 const FeatureInfo::FeatureFlags& features() const {
1500 return feature_info_->feature_flags();
1503 const FeatureInfo::Workarounds& workarounds() const {
1504 return feature_info_->workarounds();
1507 bool ShouldDeferDraws() {
1508 return !offscreen_target_frame_buffer_.get() &&
1509 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1510 surface_->DeferDraws();
1513 bool ShouldDeferReads() {
1514 return !offscreen_target_frame_buffer_.get() &&
1515 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1516 surface_->DeferDraws();
1519 error::Error WillAccessBoundFramebufferForDraw() {
1520 if (ShouldDeferDraws())
1521 return error::kDeferCommandUntilLater;
1522 if (!offscreen_target_frame_buffer_.get() &&
1523 !framebuffer_state_.bound_draw_framebuffer.get() &&
1524 !surface_->SetBackbufferAllocation(true))
1525 return error::kLostContext;
1526 return error::kNoError;
1529 error::Error WillAccessBoundFramebufferForRead() {
1530 if (ShouldDeferReads())
1531 return error::kDeferCommandUntilLater;
1532 if (!offscreen_target_frame_buffer_.get() &&
1533 !framebuffer_state_.bound_read_framebuffer.get() &&
1534 !surface_->SetBackbufferAllocation(true))
1535 return error::kLostContext;
1536 return error::kNoError;
1539 void ProcessPendingReadPixels();
1540 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1542 // Generate a member function prototype for each command in an automated and
1544 #define GLES2_CMD_OP(name) \
1545 Error Handle ## name( \
1546 uint32 immediate_data_size, \
1547 const cmds::name& args); \
1549 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1553 // The GL context this decoder renders to on behalf of the client.
1554 scoped_refptr<gfx::GLSurface> surface_;
1555 scoped_refptr<gfx::GLContext> context_;
1557 // The ContextGroup for this decoder uses to track resources.
1558 scoped_refptr<ContextGroup> group_;
1560 DebugMarkerManager debug_marker_manager_;
1563 // All the state for this context.
1564 ContextState state_;
1566 // Current width and height of the offscreen frame buffer.
1567 gfx::Size offscreen_size_;
1569 // Util to help with GL.
1572 // unpack flip y as last set by glPixelStorei
1573 bool unpack_flip_y_;
1575 // unpack (un)premultiply alpha as last set by glPixelStorei
1576 bool unpack_premultiply_alpha_;
1577 bool unpack_unpremultiply_alpha_;
1579 // Default vertex attribs manager, used when no VAOs are bound.
1580 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
1582 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1583 GLuint attrib_0_buffer_id_;
1585 // The value currently in attrib_0.
1586 Vec4 attrib_0_value_;
1588 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1589 bool attrib_0_buffer_matches_value_;
1591 // The size of attrib 0.
1592 GLsizei attrib_0_size_;
1594 // The buffer used to simulate GL_FIXED attribs.
1595 GLuint fixed_attrib_buffer_id_;
1597 // The size of fiixed attrib buffer.
1598 GLsizei fixed_attrib_buffer_size_;
1600 // The offscreen frame buffer that the client renders to. With EGL, the
1601 // depth and stencil buffers are separate. With regular GL there is a single
1602 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1603 // offscreen_target_stencil_render_buffer_ is unused.
1604 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1605 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1606 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1607 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1608 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1609 GLenum offscreen_target_color_format_;
1610 GLenum offscreen_target_depth_format_;
1611 GLenum offscreen_target_stencil_format_;
1612 GLsizei offscreen_target_samples_;
1613 GLboolean offscreen_target_buffer_preserved_;
1615 // The copy that is saved when SwapBuffers is called.
1616 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1617 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1618 scoped_refptr<TextureRef>
1619 offscreen_saved_color_texture_info_;
1621 // The copy that is used as the destination for multi-sample resolves.
1622 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1623 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1624 GLenum offscreen_saved_color_format_;
1626 scoped_ptr<QueryManager> query_manager_;
1628 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1630 base::Callback<void(gfx::Size, float)> resize_callback_;
1632 WaitSyncPointCallback wait_sync_point_callback_;
1634 ShaderCacheCallback shader_cache_callback_;
1636 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1638 // The format of the back buffer_
1639 GLenum back_buffer_color_format_;
1640 bool back_buffer_has_depth_;
1641 bool back_buffer_has_stencil_;
1643 // Backbuffer attachments that are currently undefined.
1644 uint32 backbuffer_needs_clear_bits_;
1646 // The current decoder error.
1647 error::Error current_decoder_error_;
1649 bool use_shader_translator_;
1650 scoped_refptr<ShaderTranslator> vertex_translator_;
1651 scoped_refptr<ShaderTranslator> fragment_translator_;
1653 DisallowedFeatures disallowed_features_;
1655 // Cached from ContextGroup
1656 const Validators* validators_;
1657 scoped_refptr<FeatureInfo> feature_info_;
1661 bool has_robustness_extension_;
1662 GLenum reset_status_;
1663 bool reset_by_robustness_extension_;
1665 // These flags are used to override the state of the shared feature_info_
1666 // member. Because the same FeatureInfo instance may be shared among many
1667 // contexts, the assumptions on the availablity of extensions in WebGL
1668 // contexts may be broken. These flags override the shared state to preserve
1670 bool force_webgl_glsl_validation_;
1671 bool derivatives_explicitly_enabled_;
1672 bool frag_depth_explicitly_enabled_;
1673 bool draw_buffers_explicitly_enabled_;
1675 bool compile_shader_always_succeeds_;
1678 bool service_logging_;
1680 #if defined(OS_MACOSX)
1681 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1682 TextureToIOSurfaceMap texture_to_io_surface_map_;
1685 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1687 // Cached values of the currently assigned viewport dimensions.
1688 GLsizei viewport_max_width_;
1689 GLsizei viewport_max_height_;
1691 // Command buffer stats.
1692 base::TimeDelta total_processing_commands_time_;
1694 // States related to each manager.
1695 DecoderTextureState texture_state_;
1696 DecoderFramebufferState framebuffer_state_;
1698 scoped_ptr<GPUTracer> gpu_tracer_;
1699 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1700 int gpu_trace_level_;
1701 bool gpu_trace_commands_;
1703 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1705 // Used to validate multisample renderbuffers if needed
1706 GLuint validation_texture_;
1707 GLuint validation_fbo_multisample_;
1708 GLuint validation_fbo_;
1710 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1713 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1714 const char* function_name, ErrorState* error_state)
1715 : function_name_(function_name),
1716 error_state_(error_state) {
1717 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1720 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1721 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1724 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1725 TextureUnit& info = state->texture_units[0];
1727 scoped_refptr<TextureRef> texture_ref;
1730 texture_ref = info.bound_texture_2d;
1732 case GL_TEXTURE_CUBE_MAP:
1733 texture_ref = info.bound_texture_cube_map;
1735 case GL_TEXTURE_EXTERNAL_OES:
1736 texture_ref = info.bound_texture_external_oes;
1738 case GL_TEXTURE_RECTANGLE_ARB:
1739 texture_ref = info.bound_texture_rectangle_arb;
1745 if (texture_ref.get()) {
1746 last_id = texture_ref->service_id();
1751 glBindTexture(target, last_id);
1752 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1755 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1760 ScopedGLErrorSuppressor suppressor(
1761 "ScopedTextureBinder::ctor", state_->GetErrorState());
1763 // TODO(apatrick): Check if there are any other states that need to be reset
1764 // before binding a new texture.
1765 glActiveTexture(GL_TEXTURE0);
1766 glBindTexture(target, id);
1769 ScopedTextureBinder::~ScopedTextureBinder() {
1770 ScopedGLErrorSuppressor suppressor(
1771 "ScopedTextureBinder::dtor", state_->GetErrorState());
1772 RestoreCurrentTextureBindings(state_, target_);
1775 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1778 ScopedGLErrorSuppressor suppressor(
1779 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1780 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1783 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1784 ScopedGLErrorSuppressor suppressor(
1785 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1786 state_->RestoreRenderbufferBindings();
1789 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1791 : decoder_(decoder) {
1792 ScopedGLErrorSuppressor suppressor(
1793 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1794 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1795 decoder->OnFboChanged();
1798 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1799 ScopedGLErrorSuppressor suppressor(
1800 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1801 decoder_->RestoreCurrentFramebufferBindings();
1804 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1805 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1806 : decoder_(decoder) {
1807 resolve_and_bind_ = (
1808 decoder_->offscreen_target_frame_buffer_.get() &&
1809 decoder_->IsOffscreenBufferMultisampled() &&
1810 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1811 enforce_internal_framebuffer));
1812 if (!resolve_and_bind_)
1815 ScopedGLErrorSuppressor suppressor(
1816 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1817 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1818 decoder_->offscreen_target_frame_buffer_->id());
1821 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1822 decoder_->offscreen_resolved_frame_buffer_.reset(
1823 new BackFramebuffer(decoder_));
1824 decoder_->offscreen_resolved_frame_buffer_->Create();
1825 decoder_->offscreen_resolved_color_texture_.reset(
1826 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1827 decoder_->offscreen_resolved_color_texture_->Create();
1829 DCHECK(decoder_->offscreen_saved_color_format_);
1830 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1831 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1833 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1834 decoder_->offscreen_resolved_color_texture_.get());
1835 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1836 GL_FRAMEBUFFER_COMPLETE) {
1837 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1838 << "because offscreen resolved FBO was incomplete.";
1842 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1844 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1846 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1847 const int width = decoder_->offscreen_size_.width();
1848 const int height = decoder_->offscreen_size_.height();
1849 glDisable(GL_SCISSOR_TEST);
1850 decoder->BlitFramebufferHelper(0,
1858 GL_COLOR_BUFFER_BIT,
1860 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1863 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1864 if (!resolve_and_bind_)
1867 ScopedGLErrorSuppressor suppressor(
1868 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1869 decoder_->RestoreCurrentFramebufferBindings();
1870 if (decoder_->state_.enable_flags.scissor_test) {
1871 glEnable(GL_SCISSOR_TEST);
1875 BackTexture::BackTexture(
1876 MemoryTracker* memory_tracker,
1877 ContextState* state)
1878 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1880 bytes_allocated_(0),
1884 BackTexture::~BackTexture() {
1885 // This does not destroy the render texture because that would require that
1886 // the associated GL context was current. Just check that it was explicitly
1891 void BackTexture::Create() {
1892 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1893 state_->GetErrorState());
1895 glGenTextures(1, &id_);
1896 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1897 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1898 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1900 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1902 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1903 // never called on an offscreen context, no data will ever be uploaded to the
1904 // saved offscreen color texture (it is deferred until to when SwapBuffers
1905 // is called). My idea is that some nvidia drivers might have a bug where
1906 // deleting a texture that has never been populated might cause a
1909 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1911 bytes_allocated_ = 16u * 16u * 4u;
1912 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1915 bool BackTexture::AllocateStorage(
1916 const gfx::Size& size, GLenum format, bool zero) {
1918 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
1919 state_->GetErrorState());
1920 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1921 uint32 image_size = 0;
1922 GLES2Util::ComputeImageDataSizes(
1923 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1926 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1930 scoped_ptr<char[]> zero_data;
1932 zero_data.reset(new char[image_size]);
1933 memset(zero_data.get(), 0, image_size);
1936 glTexImage2D(GL_TEXTURE_2D,
1948 bool success = glGetError() == GL_NO_ERROR;
1950 memory_tracker_.TrackMemFree(bytes_allocated_);
1951 bytes_allocated_ = image_size;
1952 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1957 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
1959 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
1960 state_->GetErrorState());
1961 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1962 glCopyTexImage2D(GL_TEXTURE_2D,
1971 void BackTexture::Destroy() {
1973 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
1974 state_->GetErrorState());
1975 glDeleteTextures(1, &id_);
1978 memory_tracker_.TrackMemFree(bytes_allocated_);
1979 bytes_allocated_ = 0;
1982 void BackTexture::Invalidate() {
1986 BackRenderbuffer::BackRenderbuffer(
1987 RenderbufferManager* renderbuffer_manager,
1988 MemoryTracker* memory_tracker,
1989 ContextState* state)
1990 : renderbuffer_manager_(renderbuffer_manager),
1991 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1993 bytes_allocated_(0),
1997 BackRenderbuffer::~BackRenderbuffer() {
1998 // This does not destroy the render buffer because that would require that
1999 // the associated GL context was current. Just check that it was explicitly
2004 void BackRenderbuffer::Create() {
2005 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2006 state_->GetErrorState());
2008 glGenRenderbuffersEXT(1, &id_);
2011 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2012 const gfx::Size& size,
2015 ScopedGLErrorSuppressor suppressor(
2016 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2017 ScopedRenderBufferBinder binder(state_, id_);
2019 uint32 estimated_size = 0;
2020 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2021 size.width(), size.height(), samples, format, &estimated_size)) {
2025 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2030 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2035 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2042 bool success = glGetError() == GL_NO_ERROR;
2044 // Mark the previously allocated bytes as free.
2045 memory_tracker_.TrackMemFree(bytes_allocated_);
2046 bytes_allocated_ = estimated_size;
2047 // Track the newly allocated bytes.
2048 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2053 void BackRenderbuffer::Destroy() {
2055 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2056 state_->GetErrorState());
2057 glDeleteRenderbuffersEXT(1, &id_);
2060 memory_tracker_.TrackMemFree(bytes_allocated_);
2061 bytes_allocated_ = 0;
2064 void BackRenderbuffer::Invalidate() {
2068 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2069 : decoder_(decoder),
2073 BackFramebuffer::~BackFramebuffer() {
2074 // This does not destroy the frame buffer because that would require that
2075 // the associated GL context was current. Just check that it was explicitly
2080 void BackFramebuffer::Create() {
2081 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2082 decoder_->GetErrorState());
2084 glGenFramebuffersEXT(1, &id_);
2087 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2089 ScopedGLErrorSuppressor suppressor(
2090 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2091 ScopedFrameBufferBinder binder(decoder_, id_);
2092 GLuint attach_id = texture ? texture->id() : 0;
2093 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2094 GL_COLOR_ATTACHMENT0,
2100 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2101 BackRenderbuffer* render_buffer) {
2103 ScopedGLErrorSuppressor suppressor(
2104 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2105 ScopedFrameBufferBinder binder(decoder_, id_);
2106 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2107 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2113 void BackFramebuffer::Destroy() {
2115 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2116 decoder_->GetErrorState());
2117 glDeleteFramebuffersEXT(1, &id_);
2122 void BackFramebuffer::Invalidate() {
2126 GLenum BackFramebuffer::CheckStatus() {
2128 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2129 decoder_->GetErrorState());
2130 ScopedFrameBufferBinder binder(decoder_, id_);
2131 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2134 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2135 return new GLES2DecoderImpl(group);
2138 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2141 logger_(&debug_marker_manager_),
2142 state_(group_->feature_info(), &logger_),
2143 unpack_flip_y_(false),
2144 unpack_premultiply_alpha_(false),
2145 unpack_unpremultiply_alpha_(false),
2146 attrib_0_buffer_id_(0),
2147 attrib_0_buffer_matches_value_(true),
2149 fixed_attrib_buffer_id_(0),
2150 fixed_attrib_buffer_size_(0),
2151 offscreen_target_color_format_(0),
2152 offscreen_target_depth_format_(0),
2153 offscreen_target_stencil_format_(0),
2154 offscreen_target_samples_(0),
2155 offscreen_target_buffer_preserved_(true),
2156 offscreen_saved_color_format_(0),
2157 back_buffer_color_format_(0),
2158 back_buffer_has_depth_(false),
2159 back_buffer_has_stencil_(false),
2160 backbuffer_needs_clear_bits_(0),
2161 current_decoder_error_(error::kNoError),
2162 use_shader_translator_(true),
2163 validators_(group_->feature_info()->validators()),
2164 feature_info_(group_->feature_info()),
2166 has_robustness_extension_(false),
2167 reset_status_(GL_NO_ERROR),
2168 reset_by_robustness_extension_(false),
2169 force_webgl_glsl_validation_(false),
2170 derivatives_explicitly_enabled_(false),
2171 frag_depth_explicitly_enabled_(false),
2172 draw_buffers_explicitly_enabled_(false),
2173 compile_shader_always_succeeds_(false),
2174 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2175 switches::kEnableGPUServiceLoggingGPU)),
2176 viewport_max_width_(0),
2177 viewport_max_height_(0),
2178 texture_state_(group_->feature_info()
2180 .texsubimage2d_faster_than_teximage2d),
2181 validation_texture_(0),
2182 validation_fbo_multisample_(0),
2183 validation_fbo_(0) {
2186 attrib_0_value_.v[0] = 0.0f;
2187 attrib_0_value_.v[1] = 0.0f;
2188 attrib_0_value_.v[2] = 0.0f;
2189 attrib_0_value_.v[3] = 1.0f;
2191 // The shader translator is used for WebGL even when running on EGL
2192 // because additional restrictions are needed (like only enabling
2193 // GL_OES_standard_derivatives on demand). It is used for the unit
2194 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2195 // the empty string to CompileShader and this is not a valid shader.
2196 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2197 CommandLine::ForCurrentProcess()->HasSwitch(
2198 switches::kDisableGLSLTranslator)) {
2199 use_shader_translator_ = false;
2203 GLES2DecoderImpl::~GLES2DecoderImpl() {
2206 bool GLES2DecoderImpl::Initialize(
2207 const scoped_refptr<gfx::GLSurface>& surface,
2208 const scoped_refptr<gfx::GLContext>& context,
2210 const gfx::Size& size,
2211 const DisallowedFeatures& disallowed_features,
2212 const std::vector<int32>& attribs) {
2213 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2214 DCHECK(context->IsCurrent(surface.get()));
2215 DCHECK(!context_.get());
2218 gpu_tracer_ = GPUTracer::Create(this);
2219 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2220 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2221 gpu_trace_level_ = 2;
2222 gpu_trace_commands_ = false;
2224 if (CommandLine::ForCurrentProcess()->HasSwitch(
2225 switches::kEnableGPUDebugging)) {
2229 if (CommandLine::ForCurrentProcess()->HasSwitch(
2230 switches::kEnableGPUCommandLogging)) {
2231 set_log_commands(true);
2234 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2235 switches::kCompileShaderAlwaysSucceeds);
2238 // Take ownership of the context and surface. The surface can be replaced with
2243 ContextCreationAttribHelper attrib_parser;
2244 if (!attrib_parser.Parse(attribs))
2247 // If the failIfMajorPerformanceCaveat context creation attribute was true
2248 // and we are using a software renderer, fail.
2249 if (attrib_parser.fail_if_major_perf_caveat_ &&
2250 feature_info_->feature_flags().is_swiftshader) {
2251 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2256 if (!group_->Initialize(this, disallowed_features)) {
2257 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2258 << "failed to initialize.";
2259 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2265 disallowed_features_ = disallowed_features;
2267 state_.attrib_values.resize(group_->max_vertex_attribs());
2268 default_vertex_attrib_manager_ = new VertexAttribManager();
2269 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2271 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2272 DoBindVertexArrayOES(0);
2274 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2275 vertex_array_manager_.reset(new VertexArrayManager());
2277 util_.set_num_compressed_texture_formats(
2278 validators_->compressed_texture_format.GetValues().size());
2280 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2281 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2282 // OpenGL ES 2.0 does not have this issue.
2283 glEnableVertexAttribArray(0);
2285 glGenBuffersARB(1, &attrib_0_buffer_id_);
2286 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2287 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2288 glBindBuffer(GL_ARRAY_BUFFER, 0);
2289 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2291 state_.texture_units.resize(group_->max_texture_units());
2292 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2293 glActiveTexture(GL_TEXTURE0 + tt);
2294 // We want the last bind to be 2D.
2296 if (features().oes_egl_image_external) {
2297 ref = texture_manager()->GetDefaultTextureInfo(
2298 GL_TEXTURE_EXTERNAL_OES);
2299 state_.texture_units[tt].bound_texture_external_oes = ref;
2300 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
2302 if (features().arb_texture_rectangle) {
2303 ref = texture_manager()->GetDefaultTextureInfo(
2304 GL_TEXTURE_RECTANGLE_ARB);
2305 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2306 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
2308 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2309 state_.texture_units[tt].bound_texture_cube_map = ref;
2310 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2311 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2312 state_.texture_units[tt].bound_texture_2d = ref;
2313 glBindTexture(GL_TEXTURE_2D, ref->service_id());
2315 glActiveTexture(GL_TEXTURE0);
2319 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2320 features().chromium_framebuffer_multisample) {
2321 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2322 // max_sample_count must be initialized to a sane value. If
2323 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2324 GLint max_sample_count = 1;
2325 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2326 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2329 offscreen_target_samples_ = 1;
2331 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2333 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2334 const bool rgb8_supported =
2335 context_->HasExtension("GL_OES_rgb8_rgba8");
2336 // The only available default render buffer formats in GLES2 have very
2337 // little precision. Don't enable multisampling unless 8-bit render
2338 // buffer formats are available--instead fall back to 8-bit textures.
2339 if (rgb8_supported && offscreen_target_samples_ > 1) {
2340 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2343 offscreen_target_samples_ = 1;
2344 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2348 // ANGLE only supports packed depth/stencil formats, so use it if it is
2350 const bool depth24_stencil8_supported =
2351 feature_info_->feature_flags().packed_depth24_stencil8;
2352 VLOG(1) << "GL_OES_packed_depth_stencil "
2353 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2354 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2355 depth24_stencil8_supported) {
2356 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2357 offscreen_target_stencil_format_ = 0;
2359 // It may be the case that this depth/stencil combination is not
2360 // supported, but this will be checked later by CheckFramebufferStatus.
2361 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2362 GL_DEPTH_COMPONENT16 : 0;
2363 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2364 GL_STENCIL_INDEX8 : 0;
2367 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2370 // If depth is requested at all, use the packed depth stencil format if
2371 // it's available, as some desktop GL drivers don't support any non-packed
2372 // formats for depth attachments.
2373 const bool depth24_stencil8_supported =
2374 feature_info_->feature_flags().packed_depth24_stencil8;
2375 VLOG(1) << "GL_EXT_packed_depth_stencil "
2376 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2378 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2379 depth24_stencil8_supported) {
2380 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2381 offscreen_target_stencil_format_ = 0;
2383 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2384 GL_DEPTH_COMPONENT : 0;
2385 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2386 GL_STENCIL_INDEX : 0;
2390 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2393 // Create the target frame buffer. This is the one that the client renders
2395 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2396 offscreen_target_frame_buffer_->Create();
2397 // Due to GLES2 format limitations, either the color texture (for
2398 // non-multisampling) or the color render buffer (for multisampling) will be
2399 // attached to the offscreen frame buffer. The render buffer has more
2400 // limited formats available to it, but the texture can't do multisampling.
2401 if (IsOffscreenBufferMultisampled()) {
2402 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2403 renderbuffer_manager(), memory_tracker(), &state_));
2404 offscreen_target_color_render_buffer_->Create();
2406 offscreen_target_color_texture_.reset(new BackTexture(
2407 memory_tracker(), &state_));
2408 offscreen_target_color_texture_->Create();
2410 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2411 renderbuffer_manager(), memory_tracker(), &state_));
2412 offscreen_target_depth_render_buffer_->Create();
2413 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2414 renderbuffer_manager(), memory_tracker(), &state_));
2415 offscreen_target_stencil_render_buffer_->Create();
2417 // Create the saved offscreen texture. The target frame buffer is copied
2418 // here when SwapBuffers is called.
2419 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2420 offscreen_saved_frame_buffer_->Create();
2422 offscreen_saved_color_texture_.reset(new BackTexture(
2423 memory_tracker(), &state_));
2424 offscreen_saved_color_texture_->Create();
2426 // Allocate the render buffers at their initial size and check the status
2427 // of the frame buffers is okay.
2428 if (!ResizeOffscreenFrameBuffer(size)) {
2429 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2434 // Allocate the offscreen saved color texture.
2435 DCHECK(offscreen_saved_color_format_);
2436 offscreen_saved_color_texture_->AllocateStorage(
2437 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2439 offscreen_saved_frame_buffer_->AttachRenderTexture(
2440 offscreen_saved_color_texture_.get());
2441 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2442 GL_FRAMEBUFFER_COMPLETE) {
2443 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2448 // Bind to the new default frame buffer (the offscreen target frame buffer).
2449 // This should now be associated with ID zero.
2450 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2452 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2453 // These are NOT if the back buffer has these proprorties. They are
2454 // if we want the command buffer to enforce them regardless of what
2455 // the real backbuffer is assuming the real back buffer gives us more than
2456 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2457 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2458 // can't do anything about that.
2461 glGetIntegerv(GL_ALPHA_BITS, &v);
2462 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2463 // user requested RGB then RGB. If the user did not specify a preference
2464 // than use whatever we were given. Same for DEPTH and STENCIL.
2465 back_buffer_color_format_ =
2466 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2467 glGetIntegerv(GL_DEPTH_BITS, &v);
2468 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2469 glGetIntegerv(GL_STENCIL_BITS, &v);
2470 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2473 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2474 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2475 // isn't well documented; it was discovered in the Khronos OpenGL ES
2476 // mailing list archives. It also implicitly enables the desktop GL
2477 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2478 // variable in fragment shaders.
2479 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2480 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2481 glEnable(GL_POINT_SPRITE);
2484 has_robustness_extension_ =
2485 context->HasExtension("GL_ARB_robustness") ||
2486 context->HasExtension("GL_EXT_robustness");
2488 if (!InitializeShaderTranslator()) {
2492 state_.viewport_width = size.width();
2493 state_.viewport_height = size.height();
2495 GLint viewport_params[4] = { 0 };
2496 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2497 viewport_max_width_ = viewport_params[0];
2498 viewport_max_height_ = viewport_params[1];
2500 state_.scissor_width = state_.viewport_width;
2501 state_.scissor_height = state_.viewport_height;
2503 // Set all the default state because some GL drivers get it wrong.
2504 state_.InitCapabilities();
2506 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2508 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2509 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2510 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2511 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2513 bool call_gl_clear = true;
2514 #if defined(OS_ANDROID)
2515 // Temporary workaround for Android WebView because this clear ignores the
2516 // clip and corrupts that external UI of the App. Not calling glClear is ok
2517 // because the system already clears the buffer before each draw. Proper
2518 // fix might be setting the scissor clip properly before initialize. See
2519 // crbug.com/259023 for details.
2520 call_gl_clear = surface_->GetHandle();
2522 if (call_gl_clear) {
2523 // Clear the backbuffer.
2524 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2527 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2528 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2531 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2532 context_->SetUnbindFboOnMakeCurrent();
2535 if (feature_info_->workarounds().release_image_after_use) {
2536 image_manager()->SetReleaseAfterUse();
2539 // Only compositor contexts are known to use only the subset of GL
2540 // that can be safely migrated between the iGPU and the dGPU. Mark
2541 // those contexts as safe to forcibly transition between the GPUs.
2542 // http://crbug.com/180876, http://crbug.com/227228
2544 context_->SetSafeToForceGpuSwitch();
2546 async_pixel_transfer_manager_.reset(
2547 AsyncPixelTransferManager::Create(context.get()));
2548 async_pixel_transfer_manager_->Initialize(texture_manager());
2550 framebuffer_manager()->AddObserver(this);
2555 Capabilities GLES2DecoderImpl::GetCapabilities() {
2556 DCHECK(initialized());
2560 caps.fast_npot_mo8_textures =
2561 feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
2562 caps.egl_image_external =
2563 feature_info_->feature_flags().oes_egl_image_external;
2564 caps.texture_format_bgra8888 =
2565 feature_info_->feature_flags().ext_texture_format_bgra8888;
2566 caps.texture_format_etc1 =
2567 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2568 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2569 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2570 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2571 caps.discard_framebuffer =
2572 feature_info_->feature_flags().ext_discard_framebuffer;
2574 #if defined(OS_MACOSX)
2575 // This is unconditionally true on mac, no need to test for it at runtime.
2576 caps.iosurface = true;
2579 caps.post_sub_buffer = surface_->HasExtension("GL_CHROMIUM_post_sub_buffer");
2584 void GLES2DecoderImpl::UpdateCapabilities() {
2585 util_.set_num_compressed_texture_formats(
2586 validators_->compressed_texture_format.GetValues().size());
2587 util_.set_num_shader_binary_formats(
2588 validators_->shader_binary_format.GetValues().size());
2591 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2592 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2594 if (!use_shader_translator_) {
2597 ShBuiltInResources resources;
2598 ShInitBuiltInResources(&resources);
2599 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2600 resources.MaxVertexUniformVectors =
2601 group_->max_vertex_uniform_vectors();
2602 resources.MaxVaryingVectors = group_->max_varying_vectors();
2603 resources.MaxVertexTextureImageUnits =
2604 group_->max_vertex_texture_image_units();
2605 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2606 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2607 resources.MaxFragmentUniformVectors =
2608 group_->max_fragment_uniform_vectors();
2609 resources.MaxDrawBuffers = group_->max_draw_buffers();
2610 resources.MaxExpressionComplexity = 256;
2611 resources.MaxCallStackDepth = 256;
2613 #if (ANGLE_SH_VERSION >= 110)
2614 GLint range[2] = { 0, 0 };
2615 GLint precision = 0;
2616 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2618 resources.FragmentPrecisionHigh =
2619 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2622 if (force_webgl_glsl_validation_) {
2623 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2624 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2625 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2626 if (!draw_buffers_explicitly_enabled_)
2627 resources.MaxDrawBuffers = 1;
2629 resources.OES_standard_derivatives =
2630 features().oes_standard_derivatives ? 1 : 0;
2631 resources.ARB_texture_rectangle =
2632 features().arb_texture_rectangle ? 1 : 0;
2633 resources.OES_EGL_image_external =
2634 features().oes_egl_image_external ? 1 : 0;
2635 resources.EXT_draw_buffers =
2636 features().ext_draw_buffers ? 1 : 0;
2637 resources.EXT_frag_depth =
2638 features().ext_frag_depth ? 1 : 0;
2641 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2643 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2644 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2645 resources.HashFunction = &CityHashForAngle;
2647 resources.HashFunction = &CityHash64;
2650 resources.HashFunction = NULL;
2651 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2652 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2653 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2654 int driver_bug_workarounds = 0;
2655 if (workarounds().needs_glsl_built_in_function_emulation)
2656 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2657 if (workarounds().init_gl_position_in_vertex_shader)
2658 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2659 if (workarounds().unfold_short_circuit_as_ternary_operation)
2660 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2661 if (workarounds().init_varyings_without_static_use)
2662 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2664 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2665 vertex_translator_ = cache->GetTranslator(
2666 SH_VERTEX_SHADER, shader_spec, &resources,
2667 implementation_type,
2668 static_cast<ShCompileOptions>(driver_bug_workarounds));
2669 if (!vertex_translator_.get()) {
2670 LOG(ERROR) << "Could not initialize vertex shader translator.";
2675 fragment_translator_ = cache->GetTranslator(
2676 SH_FRAGMENT_SHADER, shader_spec, &resources,
2677 implementation_type,
2678 static_cast<ShCompileOptions>(driver_bug_workarounds));
2679 if (!fragment_translator_.get()) {
2680 LOG(ERROR) << "Could not initialize fragment shader translator.";
2687 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2688 for (GLsizei ii = 0; ii < n; ++ii) {
2689 if (GetBuffer(client_ids[ii])) {
2693 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2694 glGenBuffersARB(n, service_ids.get());
2695 for (GLsizei ii = 0; ii < n; ++ii) {
2696 CreateBuffer(client_ids[ii], service_ids[ii]);
2701 bool GLES2DecoderImpl::GenFramebuffersHelper(
2702 GLsizei n, const GLuint* client_ids) {
2703 for (GLsizei ii = 0; ii < n; ++ii) {
2704 if (GetFramebuffer(client_ids[ii])) {
2708 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2709 glGenFramebuffersEXT(n, service_ids.get());
2710 for (GLsizei ii = 0; ii < n; ++ii) {
2711 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2716 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2717 GLsizei n, const GLuint* client_ids) {
2718 for (GLsizei ii = 0; ii < n; ++ii) {
2719 if (GetRenderbuffer(client_ids[ii])) {
2723 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2724 glGenRenderbuffersEXT(n, service_ids.get());
2725 for (GLsizei ii = 0; ii < n; ++ii) {
2726 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2731 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2732 for (GLsizei ii = 0; ii < n; ++ii) {
2733 if (GetTexture(client_ids[ii])) {
2737 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2738 glGenTextures(n, service_ids.get());
2739 for (GLsizei ii = 0; ii < n; ++ii) {
2740 CreateTexture(client_ids[ii], service_ids[ii]);
2745 void GLES2DecoderImpl::DeleteBuffersHelper(
2746 GLsizei n, const GLuint* client_ids) {
2747 for (GLsizei ii = 0; ii < n; ++ii) {
2748 Buffer* buffer = GetBuffer(client_ids[ii]);
2749 if (buffer && !buffer->IsDeleted()) {
2750 state_.vertex_attrib_manager->Unbind(buffer);
2751 if (state_.bound_array_buffer.get() == buffer) {
2752 state_.bound_array_buffer = NULL;
2754 RemoveBuffer(client_ids[ii]);
2759 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2760 GLsizei n, const GLuint* client_ids) {
2761 bool supports_separate_framebuffer_binds =
2762 features().chromium_framebuffer_multisample;
2764 for (GLsizei ii = 0; ii < n; ++ii) {
2765 Framebuffer* framebuffer =
2766 GetFramebuffer(client_ids[ii]);
2767 if (framebuffer && !framebuffer->IsDeleted()) {
2768 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2769 framebuffer_state_.bound_draw_framebuffer = NULL;
2770 framebuffer_state_.clear_state_dirty = true;
2771 GLenum target = supports_separate_framebuffer_binds ?
2772 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2773 glBindFramebufferEXT(target, GetBackbufferServiceId());
2775 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2776 framebuffer_state_.bound_read_framebuffer = NULL;
2777 GLenum target = supports_separate_framebuffer_binds ?
2778 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2779 glBindFramebufferEXT(target, GetBackbufferServiceId());
2782 RemoveFramebuffer(client_ids[ii]);
2787 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2788 GLsizei n, const GLuint* client_ids) {
2789 bool supports_separate_framebuffer_binds =
2790 features().chromium_framebuffer_multisample;
2791 for (GLsizei ii = 0; ii < n; ++ii) {
2792 Renderbuffer* renderbuffer =
2793 GetRenderbuffer(client_ids[ii]);
2794 if (renderbuffer && !renderbuffer->IsDeleted()) {
2795 if (state_.bound_renderbuffer.get() == renderbuffer) {
2796 state_.bound_renderbuffer = NULL;
2798 // Unbind from current framebuffers.
2799 if (supports_separate_framebuffer_binds) {
2800 if (framebuffer_state_.bound_read_framebuffer.get()) {
2801 framebuffer_state_.bound_read_framebuffer
2802 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2804 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2805 framebuffer_state_.bound_draw_framebuffer
2806 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2809 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2810 framebuffer_state_.bound_draw_framebuffer
2811 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2814 framebuffer_state_.clear_state_dirty = true;
2815 RemoveRenderbuffer(client_ids[ii]);
2820 void GLES2DecoderImpl::DeleteTexturesHelper(
2821 GLsizei n, const GLuint* client_ids) {
2822 bool supports_separate_framebuffer_binds =
2823 features().chromium_framebuffer_multisample;
2824 for (GLsizei ii = 0; ii < n; ++ii) {
2825 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2827 Texture* texture = texture_ref->texture();
2828 if (texture->IsAttachedToFramebuffer()) {
2829 framebuffer_state_.clear_state_dirty = true;
2831 // Unbind texture_ref from texture_ref units.
2832 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2833 state_.texture_units[jj].Unbind(texture_ref);
2835 // Unbind from current framebuffers.
2836 if (supports_separate_framebuffer_binds) {
2837 if (framebuffer_state_.bound_read_framebuffer.get()) {
2838 framebuffer_state_.bound_read_framebuffer
2839 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2841 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2842 framebuffer_state_.bound_draw_framebuffer
2843 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2846 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2847 framebuffer_state_.bound_draw_framebuffer
2848 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2851 #if defined(OS_MACOSX)
2852 GLuint service_id = texture->service_id();
2853 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2854 ReleaseIOSurfaceForTexture(service_id);
2857 RemoveTexture(client_ids[ii]);
2862 // } // anonymous namespace
2864 bool GLES2DecoderImpl::MakeCurrent() {
2865 if (!context_.get())
2868 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
2869 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2871 // Some D3D drivers cannot recover from device lost in the GPU process
2872 // sandbox. Allow a new GPU process to launch.
2873 if (workarounds().exit_on_context_lost) {
2874 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2875 << " a D3D device in the Chrome GPU process sandbox.";
2877 base::win::SetShouldCrashOnProcessDetach(false);
2885 ProcessFinishedAsyncTransfers();
2887 // Rebind the FBO if it was unbound by the context.
2888 if (workarounds().unbind_fbo_on_context_switch)
2889 RestoreFramebufferBindings();
2891 framebuffer_state_.clear_state_dirty = true;
2896 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
2897 ProcessPendingReadPixels();
2898 if (engine() && query_manager_.get())
2899 query_manager_->ProcessPendingTransferQueries();
2901 // TODO(epenner): Is there a better place to do this?
2902 // This needs to occur before we execute any batch of commands
2903 // from the client, as the client may have recieved an async
2904 // completion while issuing those commands.
2905 // "DidFlushStart" would be ideal if we had such a callback.
2906 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
2909 static void RebindCurrentFramebuffer(
2911 Framebuffer* framebuffer,
2912 GLuint back_buffer_service_id) {
2913 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
2915 if (framebuffer_id == 0) {
2916 framebuffer_id = back_buffer_service_id;
2919 glBindFramebufferEXT(target, framebuffer_id);
2922 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
2923 framebuffer_state_.clear_state_dirty = true;
2925 if (!features().chromium_framebuffer_multisample) {
2926 RebindCurrentFramebuffer(
2928 framebuffer_state_.bound_draw_framebuffer.get(),
2929 GetBackbufferServiceId());
2931 RebindCurrentFramebuffer(
2932 GL_READ_FRAMEBUFFER_EXT,
2933 framebuffer_state_.bound_read_framebuffer.get(),
2934 GetBackbufferServiceId());
2935 RebindCurrentFramebuffer(
2936 GL_DRAW_FRAMEBUFFER_EXT,
2937 framebuffer_state_.bound_draw_framebuffer.get(),
2938 GetBackbufferServiceId());
2943 bool GLES2DecoderImpl::CheckFramebufferValid(
2944 Framebuffer* framebuffer,
2945 GLenum target, const char* func_name) {
2947 if (backbuffer_needs_clear_bits_) {
2948 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2949 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2950 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2955 glDisable(GL_SCISSOR_TEST);
2956 glClear(backbuffer_needs_clear_bits_);
2957 backbuffer_needs_clear_bits_ = 0;
2958 RestoreClearState();
2963 if (framebuffer_manager()->IsComplete(framebuffer)) {
2967 GLenum completeness = framebuffer->IsPossiblyComplete();
2968 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2970 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
2974 // Are all the attachments cleared?
2975 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2976 texture_manager()->HaveUnclearedMips()) {
2977 if (!framebuffer->IsCleared()) {
2978 // Can we clear them?
2979 if (framebuffer->GetStatus(texture_manager(), target) !=
2980 GL_FRAMEBUFFER_COMPLETE) {
2982 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2983 "framebuffer incomplete (clear)");
2986 ClearUnclearedAttachments(target, framebuffer);
2990 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2991 if (framebuffer->GetStatus(texture_manager(), target) !=
2992 GL_FRAMEBUFFER_COMPLETE) {
2994 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2995 "framebuffer incomplete (check)");
2998 framebuffer_manager()->MarkAsComplete(framebuffer);
3001 // NOTE: At this point we don't know if the framebuffer is complete but
3002 // we DO know that everything that needs to be cleared has been cleared.
3006 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3007 if (!features().chromium_framebuffer_multisample) {
3008 bool valid = CheckFramebufferValid(
3009 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3017 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3018 GL_DRAW_FRAMEBUFFER_EXT,
3020 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3021 GL_READ_FRAMEBUFFER_EXT,
3025 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3026 Framebuffer* framebuffer =
3027 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3028 if (framebuffer != NULL) {
3029 const Framebuffer::Attachment* attachment =
3030 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3032 return gfx::Size(attachment->width(), attachment->height());
3034 return gfx::Size(0, 0);
3035 } else if (offscreen_target_frame_buffer_.get()) {
3036 return offscreen_size_;
3038 return surface_->GetSize();
3042 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3043 Framebuffer* framebuffer =
3044 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3045 if (framebuffer != NULL) {
3046 return framebuffer->GetColorAttachmentTextureType();
3048 return GL_UNSIGNED_BYTE;
3052 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3053 Framebuffer* framebuffer =
3054 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3055 if (framebuffer != NULL) {
3056 return framebuffer->GetColorAttachmentFormat();
3057 } else if (offscreen_target_frame_buffer_.get()) {
3058 return offscreen_target_color_format_;
3060 return back_buffer_color_format_;
3064 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3065 Framebuffer* framebuffer =
3066 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3067 if (framebuffer != NULL) {
3068 return framebuffer->GetColorAttachmentFormat();
3069 } else if (offscreen_target_frame_buffer_.get()) {
3070 return offscreen_target_color_format_;
3072 return back_buffer_color_format_;
3076 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3077 if (!offscreen_saved_color_texture_info_.get())
3079 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3080 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3081 texture_manager()->SetLevelInfo(
3082 offscreen_saved_color_texture_info_.get(),
3086 offscreen_size_.width(),
3087 offscreen_size_.height(),
3093 texture_manager()->SetParameter(
3094 "UpdateParentTextureInfo",
3096 offscreen_saved_color_texture_info_.get(),
3097 GL_TEXTURE_MAG_FILTER,
3099 texture_manager()->SetParameter(
3100 "UpdateParentTextureInfo",
3102 offscreen_saved_color_texture_info_.get(),
3103 GL_TEXTURE_MIN_FILTER,
3105 texture_manager()->SetParameter(
3106 "UpdateParentTextureInfo",
3108 offscreen_saved_color_texture_info_.get(),
3111 texture_manager()->SetParameter(
3112 "UpdateParentTextureInfo",
3114 offscreen_saved_color_texture_info_.get(),
3117 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3119 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3122 void GLES2DecoderImpl::SetResizeCallback(
3123 const base::Callback<void(gfx::Size, float)>& callback) {
3124 resize_callback_ = callback;
3127 Logger* GLES2DecoderImpl::GetLogger() {
3131 void GLES2DecoderImpl::BeginDecoding() {
3132 gpu_tracer_->BeginDecoding();
3133 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3136 void GLES2DecoderImpl::EndDecoding() {
3137 gpu_tracer_->EndDecoding();
3140 ErrorState* GLES2DecoderImpl::GetErrorState() {
3141 return state_.GetErrorState();
3144 void GLES2DecoderImpl::SetShaderCacheCallback(
3145 const ShaderCacheCallback& callback) {
3146 shader_cache_callback_ = callback;
3149 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3150 const WaitSyncPointCallback& callback) {
3151 wait_sync_point_callback_ = callback;
3154 AsyncPixelTransferManager*
3155 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3156 return async_pixel_transfer_manager_.get();
3159 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3160 async_pixel_transfer_manager_.reset();
3163 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3164 AsyncPixelTransferManager* manager) {
3165 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3168 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3169 uint32* service_texture_id) {
3170 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3172 *service_texture_id = texture_ref->service_id();
3178 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3179 return texture_state_.texture_upload_count +
3180 async_pixel_transfer_manager_->GetTextureUploadCount();
3183 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3184 return texture_state_.total_texture_upload_time +
3185 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3188 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3189 return total_processing_commands_time_;
3192 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3193 total_processing_commands_time_ += time;
3196 void GLES2DecoderImpl::Destroy(bool have_context) {
3200 DCHECK(!have_context || context_->IsCurrent(NULL));
3202 // Unbind everything.
3203 state_.vertex_attrib_manager = NULL;
3204 default_vertex_attrib_manager_ = NULL;
3205 state_.texture_units.clear();
3206 state_.bound_array_buffer = NULL;
3207 state_.current_queries.clear();
3208 framebuffer_state_.bound_read_framebuffer = NULL;
3209 framebuffer_state_.bound_draw_framebuffer = NULL;
3210 state_.bound_renderbuffer = NULL;
3212 if (offscreen_saved_color_texture_info_.get()) {
3213 DCHECK(offscreen_target_color_texture_);
3214 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3215 offscreen_saved_color_texture_->id());
3216 offscreen_saved_color_texture_->Invalidate();
3217 offscreen_saved_color_texture_info_ = NULL;
3220 if (copy_texture_CHROMIUM_.get()) {
3221 copy_texture_CHROMIUM_->Destroy();
3222 copy_texture_CHROMIUM_.reset();
3225 if (state_.current_program.get()) {
3226 program_manager()->UnuseProgram(shader_manager(),
3227 state_.current_program.get());
3230 if (attrib_0_buffer_id_) {
3231 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3233 if (fixed_attrib_buffer_id_) {
3234 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3237 if (validation_texture_) {
3238 glDeleteTextures(1, &validation_texture_);
3239 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3240 glDeleteFramebuffersEXT(1, &validation_fbo_);
3243 if (offscreen_target_frame_buffer_.get())
3244 offscreen_target_frame_buffer_->Destroy();
3245 if (offscreen_target_color_texture_.get())
3246 offscreen_target_color_texture_->Destroy();
3247 if (offscreen_target_color_render_buffer_.get())
3248 offscreen_target_color_render_buffer_->Destroy();
3249 if (offscreen_target_depth_render_buffer_.get())
3250 offscreen_target_depth_render_buffer_->Destroy();
3251 if (offscreen_target_stencil_render_buffer_.get())
3252 offscreen_target_stencil_render_buffer_->Destroy();
3253 if (offscreen_saved_frame_buffer_.get())
3254 offscreen_saved_frame_buffer_->Destroy();
3255 if (offscreen_saved_color_texture_.get())
3256 offscreen_saved_color_texture_->Destroy();
3257 if (offscreen_resolved_frame_buffer_.get())
3258 offscreen_resolved_frame_buffer_->Destroy();
3259 if (offscreen_resolved_color_texture_.get())
3260 offscreen_resolved_color_texture_->Destroy();
3262 if (offscreen_target_frame_buffer_.get())
3263 offscreen_target_frame_buffer_->Invalidate();
3264 if (offscreen_target_color_texture_.get())
3265 offscreen_target_color_texture_->Invalidate();
3266 if (offscreen_target_color_render_buffer_.get())
3267 offscreen_target_color_render_buffer_->Invalidate();
3268 if (offscreen_target_depth_render_buffer_.get())
3269 offscreen_target_depth_render_buffer_->Invalidate();
3270 if (offscreen_target_stencil_render_buffer_.get())
3271 offscreen_target_stencil_render_buffer_->Invalidate();
3272 if (offscreen_saved_frame_buffer_.get())
3273 offscreen_saved_frame_buffer_->Invalidate();
3274 if (offscreen_saved_color_texture_.get())
3275 offscreen_saved_color_texture_->Invalidate();
3276 if (offscreen_resolved_frame_buffer_.get())
3277 offscreen_resolved_frame_buffer_->Invalidate();
3278 if (offscreen_resolved_color_texture_.get())
3279 offscreen_resolved_color_texture_->Invalidate();
3282 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3283 // Otherwise, we can leak objects. http://crbug.com/258772.
3284 // state_.current_program must be reset before group_ is reset because
3285 // the later deletes the ProgramManager object that referred by
3286 // state_.current_program object.
3287 state_.current_program = NULL;
3289 copy_texture_CHROMIUM_.reset();
3291 if (query_manager_.get()) {
3292 query_manager_->Destroy(have_context);
3293 query_manager_.reset();
3296 if (vertex_array_manager_ .get()) {
3297 vertex_array_manager_->Destroy(have_context);
3298 vertex_array_manager_.reset();
3301 offscreen_target_frame_buffer_.reset();
3302 offscreen_target_color_texture_.reset();
3303 offscreen_target_color_render_buffer_.reset();
3304 offscreen_target_depth_render_buffer_.reset();
3305 offscreen_target_stencil_render_buffer_.reset();
3306 offscreen_saved_frame_buffer_.reset();
3307 offscreen_saved_color_texture_.reset();
3308 offscreen_resolved_frame_buffer_.reset();
3309 offscreen_resolved_color_texture_.reset();
3311 // Should destroy the transfer manager before the texture manager held
3312 // by the context group.
3313 async_pixel_transfer_manager_.reset();
3316 framebuffer_manager()->RemoveObserver(this);
3317 group_->Destroy(this, have_context);
3321 if (context_.get()) {
3322 context_->ReleaseCurrent(NULL);
3326 #if defined(OS_MACOSX)
3327 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3328 it != texture_to_io_surface_map_.end(); ++it) {
3329 CFRelease(it->second);
3331 texture_to_io_surface_map_.clear();
3335 void GLES2DecoderImpl::SetSurface(
3336 const scoped_refptr<gfx::GLSurface>& surface) {
3337 DCHECK(context_->IsCurrent(NULL));
3338 DCHECK(surface_.get());
3340 RestoreCurrentFramebufferBindings();
3343 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3344 if (!offscreen_saved_color_texture_.get()) {
3345 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3348 if (!offscreen_saved_color_texture_info_.get()) {
3349 GLuint service_id = offscreen_saved_color_texture_->id();
3350 offscreen_saved_color_texture_info_ = TextureRef::Create(
3351 texture_manager(), 0, service_id);
3352 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3354 UpdateParentTextureInfo();
3356 mailbox_manager()->ProduceTexture(
3357 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3360 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3361 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3362 if (!is_offscreen) {
3363 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3364 << " with an onscreen framebuffer.";
3368 if (offscreen_size_ == size)
3371 offscreen_size_ = size;
3372 int w = offscreen_size_.width();
3373 int h = offscreen_size_.height();
3374 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3375 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3376 << "to allocate storage due to excessive dimensions.";
3380 // Reallocate the offscreen target buffers.
3381 DCHECK(offscreen_target_color_format_);
3382 if (IsOffscreenBufferMultisampled()) {
3383 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3384 feature_info_, offscreen_size_, offscreen_target_color_format_,
3385 offscreen_target_samples_)) {
3386 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3387 << "to allocate storage for offscreen target color buffer.";
3391 if (!offscreen_target_color_texture_->AllocateStorage(
3392 offscreen_size_, offscreen_target_color_format_, false)) {
3393 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3394 << "to allocate storage for offscreen target color texture.";
3398 if (offscreen_target_depth_format_ &&
3399 !offscreen_target_depth_render_buffer_->AllocateStorage(
3400 feature_info_, offscreen_size_, offscreen_target_depth_format_,
3401 offscreen_target_samples_)) {
3402 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3403 << "to allocate storage for offscreen target depth buffer.";
3406 if (offscreen_target_stencil_format_ &&
3407 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3408 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
3409 offscreen_target_samples_)) {
3410 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3411 << "to allocate storage for offscreen target stencil buffer.";
3415 // Attach the offscreen target buffers to the target frame buffer.
3416 if (IsOffscreenBufferMultisampled()) {
3417 offscreen_target_frame_buffer_->AttachRenderBuffer(
3418 GL_COLOR_ATTACHMENT0,
3419 offscreen_target_color_render_buffer_.get());
3421 offscreen_target_frame_buffer_->AttachRenderTexture(
3422 offscreen_target_color_texture_.get());
3424 if (offscreen_target_depth_format_) {
3425 offscreen_target_frame_buffer_->AttachRenderBuffer(
3426 GL_DEPTH_ATTACHMENT,
3427 offscreen_target_depth_render_buffer_.get());
3429 const bool packed_depth_stencil =
3430 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3431 if (packed_depth_stencil) {
3432 offscreen_target_frame_buffer_->AttachRenderBuffer(
3433 GL_STENCIL_ATTACHMENT,
3434 offscreen_target_depth_render_buffer_.get());
3435 } else if (offscreen_target_stencil_format_) {
3436 offscreen_target_frame_buffer_->AttachRenderBuffer(
3437 GL_STENCIL_ATTACHMENT,
3438 offscreen_target_stencil_render_buffer_.get());
3441 if (offscreen_target_frame_buffer_->CheckStatus() !=
3442 GL_FRAMEBUFFER_COMPLETE) {
3443 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3444 << "because offscreen FBO was incomplete.";
3448 // Clear the target frame buffer.
3450 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3451 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3452 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3453 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3455 glStencilMaskSeparate(GL_FRONT, -1);
3456 glStencilMaskSeparate(GL_BACK, -1);
3458 glDepthMask(GL_TRUE);
3459 glDisable(GL_SCISSOR_TEST);
3460 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3461 RestoreClearState();
3464 // Destroy the offscreen resolved framebuffers.
3465 if (offscreen_resolved_frame_buffer_.get())
3466 offscreen_resolved_frame_buffer_->Destroy();
3467 if (offscreen_resolved_color_texture_.get())
3468 offscreen_resolved_color_texture_->Destroy();
3469 offscreen_resolved_color_texture_.reset();
3470 offscreen_resolved_frame_buffer_.reset();
3475 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3476 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3477 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3478 return error::kDeferCommandUntilLater;
3480 GLuint width = static_cast<GLuint>(c.width);
3481 GLuint height = static_cast<GLuint>(c.height);
3482 GLfloat scale_factor = c.scale_factor;
3483 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3485 width = std::max(1U, width);
3486 height = std::max(1U, height);
3488 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3489 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3490 // Make sure that we are done drawing to the back buffer before resizing.
3493 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3495 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3496 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3497 << "ResizeOffscreenFrameBuffer failed.";
3498 return error::kLostContext;
3502 if (!resize_callback_.is_null()) {
3503 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3504 DCHECK(context_->IsCurrent(surface_.get()));
3505 if (!context_->IsCurrent(surface_.get())) {
3506 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3507 << "current after resize callback.";
3508 return error::kLostContext;
3512 return error::kNoError;
3515 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3516 if (command_id > kStartPoint && command_id < kNumCommands) {
3517 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3519 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3522 // Decode command with its arguments, and call the corresponding GL function.
3523 // Note: args is a pointer to the command buffer. As such, it could be changed
3524 // by a (malicious) client at any time, so if validation has to happen, it
3525 // should operate on a copy of them.
3526 error::Error GLES2DecoderImpl::DoCommand(
3527 unsigned int command,
3528 unsigned int arg_count,
3529 const void* cmd_data) {
3530 error::Error result = error::kNoError;
3531 if (log_commands()) {
3532 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3533 // VLOG(1), no luck.
3534 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3535 << GetCommandName(command);
3537 unsigned int command_index = command - kStartPoint - 1;
3538 if (command_index < arraysize(g_command_info)) {
3539 const CommandInfo& info = g_command_info[command_index];
3540 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3541 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3542 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3543 bool doing_gpu_trace = false;
3544 if (gpu_trace_commands_) {
3545 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3546 doing_gpu_trace = true;
3547 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3551 uint32 immediate_data_size =
3552 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3554 #define GLES2_CMD_OP(name) \
3555 case cmds::name::kCmdId: \
3556 result = Handle ## name( \
3557 immediate_data_size, \
3558 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3561 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3565 if (doing_gpu_trace)
3566 gpu_tracer_->End(kTraceDecoder);
3570 while ((error = glGetError()) != GL_NO_ERROR) {
3571 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3572 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3573 << GetCommandName(command);
3574 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3578 result = error::kInvalidArguments;
3581 result = DoCommonCommand(command, arg_count, cmd_data);
3583 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3584 result = current_decoder_error_;
3585 current_decoder_error_ = error::kNoError;
3590 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3591 buffer_manager()->RemoveBuffer(client_id);
3594 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3595 if (GetProgram(client_id)) {
3598 GLuint service_id = glCreateProgram();
3599 if (service_id != 0) {
3600 CreateProgram(client_id, service_id);
3605 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3606 if (GetShader(client_id)) {
3609 GLuint service_id = glCreateShader(type);
3610 if (service_id != 0) {
3611 CreateShader(client_id, service_id, type);
3616 void GLES2DecoderImpl::DoFinish() {
3618 ProcessPendingReadPixels();
3619 ProcessPendingQueries();
3622 void GLES2DecoderImpl::DoFlush() {
3624 ProcessPendingQueries();
3627 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3628 GLuint texture_index = texture_unit - GL_TEXTURE0;
3629 if (texture_index >= state_.texture_units.size()) {
3630 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3631 "glActiveTexture", texture_unit, "texture_unit");
3634 state_.active_texture_unit = texture_index;
3635 glActiveTexture(texture_unit);
3638 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3639 Buffer* buffer = NULL;
3640 GLuint service_id = 0;
3641 if (client_id != 0) {
3642 buffer = GetBuffer(client_id);
3644 if (!group_->bind_generates_resource()) {
3645 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3647 "id not generated by glGenBuffers");
3651 // It's a new id so make a buffer buffer for it.
3652 glGenBuffersARB(1, &service_id);
3653 CreateBuffer(client_id, service_id);
3654 buffer = GetBuffer(client_id);
3655 IdAllocatorInterface* id_allocator =
3656 group_->GetIdAllocator(id_namespaces::kBuffers);
3657 id_allocator->MarkAsUsed(client_id);
3660 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3662 if (!buffer_manager()->SetTarget(buffer, target)) {
3664 GL_INVALID_OPERATION,
3665 "glBindBuffer", "buffer bound to more than 1 target");
3668 service_id = buffer->service_id();
3671 case GL_ARRAY_BUFFER:
3672 state_.bound_array_buffer = buffer;
3674 case GL_ELEMENT_ARRAY_BUFFER:
3675 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3678 NOTREACHED(); // Validation should prevent us getting here.
3681 glBindBuffer(target, service_id);
3684 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3685 bool all_draw_buffers) {
3686 Framebuffer* framebuffer =
3687 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3688 if (!all_draw_buffers || !framebuffer) {
3689 return (GLES2Util::GetChannelsForFormat(
3690 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3692 return framebuffer->HasAlphaMRT();
3695 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3696 Framebuffer* framebuffer =
3697 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3699 return framebuffer->HasDepthAttachment();
3701 if (offscreen_target_frame_buffer_.get()) {
3702 return offscreen_target_depth_format_ != 0;
3704 return back_buffer_has_depth_;
3707 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3708 Framebuffer* framebuffer =
3709 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3711 return framebuffer->HasStencilAttachment();
3713 if (offscreen_target_frame_buffer_.get()) {
3714 return offscreen_target_stencil_format_ != 0 ||
3715 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3717 return back_buffer_has_stencil_;
3720 void GLES2DecoderImpl::ApplyDirtyState() {
3721 if (framebuffer_state_.clear_state_dirty) {
3723 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3724 state_.color_mask_alpha &&
3725 BoundFramebufferHasColorAttachmentWithAlpha(true));
3726 bool have_depth = BoundFramebufferHasDepthAttachment();
3727 glDepthMask(state_.depth_mask && have_depth);
3728 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3729 bool have_stencil = BoundFramebufferHasStencilAttachment();
3730 glStencilMaskSeparate(
3731 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3732 glStencilMaskSeparate(
3733 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3735 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3736 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3737 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3738 EnableDisable(GL_BLEND, state_.enable_flags.blend);
3739 framebuffer_state_.clear_state_dirty = false;
3743 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3744 return (offscreen_target_frame_buffer_.get())
3745 ? offscreen_target_frame_buffer_->id()
3746 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3749 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) const {
3750 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3751 "context", logger_.GetLogPrefix());
3752 // Restore the Framebuffer first because of bugs in Intel drivers.
3753 // Intel drivers incorrectly clip the viewport settings to
3754 // the size of the current framebuffer object.
3755 RestoreFramebufferBindings();
3756 state_.RestoreState(prev_state);
3759 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3761 framebuffer_state_.bound_draw_framebuffer.get()
3762 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3763 : GetBackbufferServiceId();
3764 if (!features().chromium_framebuffer_multisample) {
3765 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3767 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3768 service_id = framebuffer_state_.bound_read_framebuffer.get()
3769 ? framebuffer_state_.bound_read_framebuffer->service_id()
3770 : GetBackbufferServiceId();
3771 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3776 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3777 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3779 GLenum target = texture->target();
3780 glBindTexture(target, service_id);
3782 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3784 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3786 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3788 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3789 RestoreTextureUnitBindings(state_.active_texture_unit);
3793 void GLES2DecoderImpl::ClearAllAttributes() const {
3794 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
3795 if (i != 0) // Never disable attribute 0
3796 glDisableVertexAttribArray(i);
3797 if(features().angle_instanced_arrays)
3798 glVertexAttribDivisorANGLE(i, 0);
3802 void GLES2DecoderImpl::RestoreAllAttributes() const {
3803 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i)
3804 RestoreAttribute(i);
3807 void GLES2DecoderImpl::OnFboChanged() const {
3808 if (workarounds().restore_scissor_on_fbo_change)
3809 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3812 // Called after the FBO is checked for completeness.
3813 void GLES2DecoderImpl::OnUseFramebuffer() const {
3814 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3815 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3816 // The driver forgets the correct scissor when modifying the FBO binding.
3817 glScissor(state_.scissor_x,
3819 state_.scissor_width,
3820 state_.scissor_height);
3822 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3823 // it's unclear how this bug works.
3828 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3829 Framebuffer* framebuffer = NULL;
3830 GLuint service_id = 0;
3831 if (client_id != 0) {
3832 framebuffer = GetFramebuffer(client_id);
3834 if (!group_->bind_generates_resource()) {
3835 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3836 "glBindFramebuffer",
3837 "id not generated by glGenFramebuffers");
3841 // It's a new id so make a framebuffer framebuffer for it.
3842 glGenFramebuffersEXT(1, &service_id);
3843 CreateFramebuffer(client_id, service_id);
3844 framebuffer = GetFramebuffer(client_id);
3845 IdAllocatorInterface* id_allocator =
3846 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3847 id_allocator->MarkAsUsed(client_id);
3849 service_id = framebuffer->service_id();
3851 framebuffer->MarkAsValid();
3853 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
3855 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3856 framebuffer_state_.bound_draw_framebuffer = framebuffer;
3859 // vmiura: This looks like dup code
3860 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3861 framebuffer_state_.bound_read_framebuffer = framebuffer;
3864 framebuffer_state_.clear_state_dirty = true;
3866 // If we are rendering to the backbuffer get the FBO id for any simulated
3868 if (framebuffer == NULL) {
3869 service_id = GetBackbufferServiceId();
3872 glBindFramebufferEXT(target, service_id);
3876 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3877 Renderbuffer* renderbuffer = NULL;
3878 GLuint service_id = 0;
3879 if (client_id != 0) {
3880 renderbuffer = GetRenderbuffer(client_id);
3881 if (!renderbuffer) {
3882 if (!group_->bind_generates_resource()) {
3883 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3884 "glBindRenderbuffer",
3885 "id not generated by glGenRenderbuffers");
3889 // It's a new id so make a renderbuffer renderbuffer for it.
3890 glGenRenderbuffersEXT(1, &service_id);
3891 CreateRenderbuffer(client_id, service_id);
3892 renderbuffer = GetRenderbuffer(client_id);
3893 IdAllocatorInterface* id_allocator =
3894 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3895 id_allocator->MarkAsUsed(client_id);
3897 service_id = renderbuffer->service_id();
3899 renderbuffer->MarkAsValid();
3901 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
3902 state_.bound_renderbuffer = renderbuffer;
3903 glBindRenderbufferEXT(target, service_id);
3906 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
3907 TextureRef* texture_ref = NULL;
3908 GLuint service_id = 0;
3909 if (client_id != 0) {
3910 texture_ref = GetTexture(client_id);
3912 if (!group_->bind_generates_resource()) {
3913 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3915 "id not generated by glGenTextures");
3919 // It's a new id so make a texture texture for it.
3920 glGenTextures(1, &service_id);
3921 DCHECK_NE(0u, service_id);
3922 CreateTexture(client_id, service_id);
3923 texture_ref = GetTexture(client_id);
3924 IdAllocatorInterface* id_allocator =
3925 group_->GetIdAllocator(id_namespaces::kTextures);
3926 id_allocator->MarkAsUsed(client_id);
3929 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
3931 Texture* texture = texture_ref->texture();
3933 // Check the texture exists
3934 // Check that we are not trying to bind it to a different target.
3935 if (texture->target() != 0 && texture->target() != target) {
3937 GL_INVALID_OPERATION,
3938 "glBindTexture", "texture bound to more than 1 target.");
3941 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3942 if (texture->target() == 0) {
3943 texture_manager()->SetTarget(texture_ref, target);
3945 glBindTexture(target, texture->service_id());
3947 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
3948 unit.bind_target = target;
3951 unit.bound_texture_2d = texture_ref;
3953 case GL_TEXTURE_CUBE_MAP:
3954 unit.bound_texture_cube_map = texture_ref;
3956 case GL_TEXTURE_EXTERNAL_OES:
3957 unit.bound_texture_external_oes = texture_ref;
3959 case GL_TEXTURE_RECTANGLE_ARB:
3960 unit.bound_texture_rectangle_arb = texture_ref;
3963 NOTREACHED(); // Validation should prevent us getting here.
3968 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
3969 if (state_.vertex_attrib_manager->Enable(index, false)) {
3971 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
3972 glDisableVertexAttribArray(index);
3977 "glDisableVertexAttribArray", "index out of range");
3981 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3982 GLsizei numAttachments,
3983 const GLenum* attachments) {
3984 if (!features().ext_discard_framebuffer) {
3985 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3986 "glDiscardFramebufferEXT",
3987 "function not available");
3991 Framebuffer* framebuffer =
3992 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3994 // Validates the attachments. If one of them fails
3995 // the whole command fails.
3996 for (GLsizei i = 0; i < numAttachments; ++i) {
3998 !validators_->attachment.IsValid(attachments[i])) ||
4000 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4001 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4002 "glDiscardFramebufferEXT", attachments[i], "attachments");
4007 // Marks each one of them as not cleared
4008 for (GLsizei i = 0; i < numAttachments; ++i) {
4010 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4015 switch (attachments[i]) {
4017 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4020 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4021 case GL_STENCIL_EXT:
4022 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4031 // If the default framebuffer is bound but we are still rendering to an
4032 // FBO, translate attachment names that refer to default framebuffer
4033 // channels to corresponding framebuffer attachments.
4034 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4035 for (GLsizei i = 0; i < numAttachments; ++i) {
4036 GLenum attachment = attachments[i];
4037 if (!framebuffer && GetBackbufferServiceId()) {
4038 switch (attachment) {
4040 attachment = GL_COLOR_ATTACHMENT0;
4043 attachment = GL_DEPTH_ATTACHMENT;
4045 case GL_STENCIL_EXT:
4046 attachment = GL_STENCIL_ATTACHMENT;
4053 translated_attachments[i] = attachment;
4056 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4059 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4060 if (state_.vertex_attrib_manager->Enable(index, true)) {
4061 glEnableVertexAttribArray(index);
4064 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4068 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4069 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4072 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4074 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4078 if (target == GL_TEXTURE_CUBE_MAP) {
4079 for (int i = 0; i < 6; ++i) {
4080 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4081 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4083 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4088 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4090 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4095 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4096 // Workaround for Mac driver bug. In the large scheme of things setting
4097 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4098 // hit so there's probably no need to make this conditional. The bug appears
4099 // to be that if the filtering mode is set to something that doesn't require
4100 // mipmaps for rendering, or is never set to something other than the default,
4101 // then glGenerateMipmap misbehaves.
4102 if (workarounds().set_texture_filter_before_generating_mipmap) {
4103 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4105 glGenerateMipmapEXT(target);
4106 if (workarounds().set_texture_filter_before_generating_mipmap) {
4107 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4108 texture_ref->texture()->min_filter());
4110 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4111 if (error == GL_NO_ERROR) {
4112 texture_manager()->MarkMipmapsGenerated(texture_ref);
4116 bool GLES2DecoderImpl::GetHelper(
4117 GLenum pname, GLint* params, GLsizei* num_written) {
4118 DCHECK(num_written);
4119 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4121 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4124 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4125 GetBoundReadFrameBufferInternalFormat());
4128 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4131 *params = GLES2Util::GetPreferredGLReadPixelsType(
4132 GetBoundReadFrameBufferInternalFormat(),
4133 GetBoundReadFrameBufferTextureType());
4136 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4139 *params = group_->max_fragment_uniform_vectors();
4142 case GL_MAX_VARYING_VECTORS:
4145 *params = group_->max_varying_vectors();
4148 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4151 *params = group_->max_vertex_uniform_vectors();
4157 case GL_MAX_VIEWPORT_DIMS:
4158 if (offscreen_target_frame_buffer_.get()) {
4161 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4162 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4167 case GL_MAX_SAMPLES:
4170 params[0] = renderbuffer_manager()->max_samples();
4173 case GL_MAX_RENDERBUFFER_SIZE:
4176 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4179 case GL_MAX_TEXTURE_SIZE:
4182 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4185 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4188 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4191 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4194 params[0] = group_->max_color_attachments();
4197 case GL_MAX_DRAW_BUFFERS_ARB:
4200 params[0] = group_->max_draw_buffers();
4207 glGetIntegerv(GL_ALPHA_BITS, &v);
4208 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4215 glGetIntegerv(GL_DEPTH_BITS, &v);
4216 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4219 case GL_STENCIL_BITS:
4223 glGetIntegerv(GL_STENCIL_BITS, &v);
4224 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4227 case GL_COMPRESSED_TEXTURE_FORMATS:
4228 *num_written = validators_->compressed_texture_format.GetValues().size();
4230 for (GLint ii = 0; ii < *num_written; ++ii) {
4231 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4235 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4238 *params = validators_->compressed_texture_format.GetValues().size();
4241 case GL_NUM_SHADER_BINARY_FORMATS:
4244 *params = validators_->shader_binary_format.GetValues().size();
4247 case GL_SHADER_BINARY_FORMATS:
4248 *num_written = validators_->shader_binary_format.GetValues().size();
4250 for (GLint ii = 0; ii < *num_written; ++ii) {
4251 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4255 case GL_SHADER_COMPILER:
4261 case GL_ARRAY_BUFFER_BINDING:
4264 if (state_.bound_array_buffer.get()) {
4265 GLuint client_id = 0;
4266 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4268 *params = client_id;
4274 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4277 if (state_.vertex_attrib_manager->element_array_buffer()) {
4278 GLuint client_id = 0;
4279 buffer_manager()->GetClientId(
4280 state_.vertex_attrib_manager->element_array_buffer()->
4281 service_id(), &client_id);
4282 *params = client_id;
4288 case GL_FRAMEBUFFER_BINDING:
4289 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4292 Framebuffer* framebuffer =
4293 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4295 GLuint client_id = 0;
4296 framebuffer_manager()->GetClientId(
4297 framebuffer->service_id(), &client_id);
4298 *params = client_id;
4304 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4307 Framebuffer* framebuffer =
4308 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4310 GLuint client_id = 0;
4311 framebuffer_manager()->GetClientId(
4312 framebuffer->service_id(), &client_id);
4313 *params = client_id;
4319 case GL_RENDERBUFFER_BINDING:
4322 Renderbuffer* renderbuffer =
4323 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4325 *params = renderbuffer->client_id();
4331 case GL_CURRENT_PROGRAM:
4334 if (state_.current_program.get()) {
4335 GLuint client_id = 0;
4336 program_manager()->GetClientId(
4337 state_.current_program->service_id(), &client_id);
4338 *params = client_id;
4344 case GL_VERTEX_ARRAY_BINDING_OES:
4347 if (state_.vertex_attrib_manager.get() !=
4348 default_vertex_attrib_manager_.get()) {
4349 GLuint client_id = 0;
4350 vertex_array_manager_->GetClientId(
4351 state_.vertex_attrib_manager->service_id(), &client_id);
4352 *params = client_id;
4358 case GL_TEXTURE_BINDING_2D:
4361 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4362 if (unit.bound_texture_2d.get()) {
4363 *params = unit.bound_texture_2d->client_id();
4369 case GL_TEXTURE_BINDING_CUBE_MAP:
4372 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4373 if (unit.bound_texture_cube_map.get()) {
4374 *params = unit.bound_texture_cube_map->client_id();
4380 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4383 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4384 if (unit.bound_texture_external_oes.get()) {
4385 *params = unit.bound_texture_external_oes->client_id();
4391 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4394 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4395 if (unit.bound_texture_rectangle_arb.get()) {
4396 *params = unit.bound_texture_rectangle_arb->client_id();
4402 case GL_UNPACK_FLIP_Y_CHROMIUM:
4405 params[0] = unpack_flip_y_;
4408 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4411 params[0] = unpack_premultiply_alpha_;
4414 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4417 params[0] = unpack_unpremultiply_alpha_;
4421 if (pname >= GL_DRAW_BUFFER0_ARB &&
4422 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4425 Framebuffer* framebuffer =
4426 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4428 params[0] = framebuffer->GetDrawBuffer(pname);
4429 } else { // backbuffer
4430 if (pname == GL_DRAW_BUFFER0_ARB)
4431 params[0] = group_->draw_buffer();
4433 params[0] = GL_NONE;
4438 *num_written = util_.GLGetNumValuesReturned(pname);
4443 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4444 GLenum pname, GLsizei* num_values) {
4445 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4448 return GetHelper(pname, NULL, num_values);
4451 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4452 if (GL_MAX_SAMPLES == pname &&
4453 features().use_img_for_multisampled_render_to_texture) {
4454 return GL_MAX_SAMPLES_IMG;
4459 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4461 GLsizei num_written = 0;
4462 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4463 scoped_ptr<GLint[]> values(new GLint[num_written]);
4464 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4465 GetHelper(pname, values.get(), &num_written);
4467 for (GLsizei ii = 0; ii < num_written; ++ii) {
4468 params[ii] = static_cast<GLboolean>(values[ii]);
4471 pname = AdjustGetPname(pname);
4472 glGetBooleanv(pname, params);
4476 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4478 GLsizei num_written = 0;
4479 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4480 if (GetHelper(pname, NULL, &num_written)) {
4481 scoped_ptr<GLint[]> values(new GLint[num_written]);
4482 GetHelper(pname, values.get(), &num_written);
4483 for (GLsizei ii = 0; ii < num_written; ++ii) {
4484 params[ii] = static_cast<GLfloat>(values[ii]);
4487 pname = AdjustGetPname(pname);
4488 glGetFloatv(pname, params);
4493 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4495 GLsizei num_written;
4496 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4497 !GetHelper(pname, params, &num_written)) {
4498 pname = AdjustGetPname(pname);
4499 glGetIntegerv(pname, params);
4503 void GLES2DecoderImpl::DoGetProgramiv(
4504 GLuint program_id, GLenum pname, GLint* params) {
4505 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4509 program->GetProgramiv(pname, params);
4512 void GLES2DecoderImpl::DoGetBufferParameteriv(
4513 GLenum target, GLenum pname, GLint* params) {
4514 // Just delegate it. Some validation is actually done before this.
4515 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4516 &state_, target, pname, params);
4519 void GLES2DecoderImpl::DoBindAttribLocation(
4520 GLuint program_id, GLuint index, const char* name) {
4521 if (!StringIsValidForGLES(name)) {
4523 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4526 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4528 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4531 if (index >= group_->max_vertex_attribs()) {
4533 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4536 Program* program = GetProgramInfoNotShader(
4537 program_id, "glBindAttribLocation");
4541 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4542 glBindAttribLocation(program->service_id(), index, name);
4545 error::Error GLES2DecoderImpl::HandleBindAttribLocation(
4546 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
4547 GLuint program = static_cast<GLuint>(c.program);
4548 GLuint index = static_cast<GLuint>(c.index);
4549 uint32 name_size = c.data_size;
4550 const char* name = GetSharedMemoryAs<const char*>(
4551 c.name_shm_id, c.name_shm_offset, name_size);
4553 return error::kOutOfBounds;
4555 String name_str(name, name_size);
4556 DoBindAttribLocation(program, index, name_str.c_str());
4557 return error::kNoError;
4560 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4561 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4562 GLuint program = static_cast<GLuint>(c.program);
4563 GLuint index = static_cast<GLuint>(c.index);
4564 Bucket* bucket = GetBucket(c.name_bucket_id);
4565 if (!bucket || bucket->size() == 0) {
4566 return error::kInvalidArguments;
4568 std::string name_str;
4569 if (!bucket->GetAsString(&name_str)) {
4570 return error::kInvalidArguments;
4572 DoBindAttribLocation(program, index, name_str.c_str());
4573 return error::kNoError;
4576 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4577 GLuint program_id, GLint location, const char* name) {
4578 if (!StringIsValidForGLES(name)) {
4581 "glBindUniformLocationCHROMIUM", "Invalid character");
4584 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4586 GL_INVALID_OPERATION,
4587 "glBindUniformLocationCHROMIUM", "reserved prefix");
4590 if (location < 0 || static_cast<uint32>(location) >=
4591 (group_->max_fragment_uniform_vectors() +
4592 group_->max_vertex_uniform_vectors()) * 4) {
4595 "glBindUniformLocationCHROMIUM", "location out of range");
4598 Program* program = GetProgramInfoNotShader(
4599 program_id, "glBindUniformLocationCHROMIUM");
4603 if (!program->SetUniformLocationBinding(name, location)) {
4606 "glBindUniformLocationCHROMIUM", "location out of range");
4610 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4611 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
4612 GLuint program = static_cast<GLuint>(c.program);
4613 GLint location = static_cast<GLint>(c.location);
4614 uint32 name_size = c.data_size;
4615 const char* name = GetSharedMemoryAs<const char*>(
4616 c.name_shm_id, c.name_shm_offset, name_size);
4618 return error::kOutOfBounds;
4620 String name_str(name, name_size);
4621 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4622 return error::kNoError;
4625 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4626 uint32 immediate_data_size,
4627 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4628 GLuint program = static_cast<GLuint>(c.program);
4629 GLint location = static_cast<GLint>(c.location);
4630 Bucket* bucket = GetBucket(c.name_bucket_id);
4631 if (!bucket || bucket->size() == 0) {
4632 return error::kInvalidArguments;
4634 std::string name_str;
4635 if (!bucket->GetAsString(&name_str)) {
4636 return error::kInvalidArguments;
4638 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4639 return error::kNoError;
4642 error::Error GLES2DecoderImpl::HandleDeleteShader(
4643 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4644 GLuint client_id = c.shader;
4646 Shader* shader = GetShader(client_id);
4648 if (!shader->IsDeleted()) {
4649 glDeleteShader(shader->service_id());
4650 shader_manager()->MarkAsDeleted(shader);
4653 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4656 return error::kNoError;
4659 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4660 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4661 GLuint client_id = c.program;
4663 Program* program = GetProgram(client_id);
4665 if (!program->IsDeleted()) {
4666 program_manager()->MarkAsDeleted(shader_manager(), program);
4670 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4673 return error::kNoError;
4676 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4677 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4678 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4679 for (GLsizei ii = 0; ii < n; ++ii) {
4680 id_allocator->FreeID(ids[ii]);
4684 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4685 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4686 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4687 GLsizei n = static_cast<GLsizei>(c.n);
4689 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4690 return error::kOutOfBounds;
4692 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4693 c.ids_shm_id, c.ids_shm_offset, data_size);
4695 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4696 return error::kNoError;
4699 return error::kOutOfBounds;
4701 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4702 return error::kNoError;
4705 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4706 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4707 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4708 if (id_offset == 0) {
4709 for (GLsizei ii = 0; ii < n; ++ii) {
4710 ids[ii] = id_allocator->AllocateID();
4713 for (GLsizei ii = 0; ii < n; ++ii) {
4714 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4715 id_offset = ids[ii] + 1;
4720 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4721 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4722 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4723 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4724 GLsizei n = static_cast<GLsizei>(c.n);
4726 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4727 return error::kOutOfBounds;
4729 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4730 c.ids_shm_id, c.ids_shm_offset, data_size);
4732 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4733 return error::kNoError;
4736 return error::kOutOfBounds;
4738 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4739 return error::kNoError;
4742 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4743 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4744 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4745 for (GLsizei ii = 0; ii < n; ++ii) {
4746 if (!id_allocator->MarkAsUsed(ids[ii])) {
4747 for (GLsizei jj = 0; jj < ii; ++jj) {
4748 id_allocator->FreeID(ids[jj]);
4751 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4752 "attempt to register id that already exists");
4758 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4759 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4760 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4761 GLsizei n = static_cast<GLsizei>(c.n);
4763 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4764 return error::kOutOfBounds;
4766 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4767 c.ids_shm_id, c.ids_shm_offset, data_size);
4769 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4770 return error::kNoError;
4773 return error::kOutOfBounds;
4775 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4776 return error::kNoError;
4779 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4780 DCHECK(!ShouldDeferDraws());
4781 if (CheckBoundFramebuffersValid("glClear")) {
4785 return error::kNoError;
4788 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4789 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4790 GLuint client_renderbuffer_id) {
4791 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4794 GL_INVALID_OPERATION,
4795 "glFramebufferRenderbuffer", "no framebuffer bound");
4798 GLuint service_id = 0;
4799 Renderbuffer* renderbuffer = NULL;
4800 if (client_renderbuffer_id) {
4801 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4802 if (!renderbuffer) {
4804 GL_INVALID_OPERATION,
4805 "glFramebufferRenderbuffer", "unknown renderbuffer");
4808 service_id = renderbuffer->service_id();
4810 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4811 glFramebufferRenderbufferEXT(
4812 target, attachment, renderbuffertarget, service_id);
4813 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4814 if (error == GL_NO_ERROR) {
4815 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4817 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4818 framebuffer_state_.clear_state_dirty = true;
4823 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4824 if (SetCapabilityState(cap, false)) {
4829 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4830 if (SetCapabilityState(cap, true)) {
4835 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4836 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4837 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4838 glDepthRange(znear, zfar);
4841 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
4842 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4843 state_.sample_coverage_invert = (invert != 0);
4844 glSampleCoverage(state_.sample_coverage_value, invert);
4847 // Assumes framebuffer is complete.
4848 void GLES2DecoderImpl::ClearUnclearedAttachments(
4849 GLenum target, Framebuffer* framebuffer) {
4850 if (target == GL_READ_FRAMEBUFFER_EXT) {
4851 // bind this to the DRAW point, clear then bind back to READ
4852 // TODO(gman): I don't think there is any guarantee that an FBO that
4853 // is complete on the READ attachment will be complete as a DRAW
4855 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4856 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
4858 GLbitfield clear_bits = 0;
4859 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
4862 (GLES2Util::GetChannelsForFormat(
4863 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4865 glColorMask(true, true, true, true);
4866 clear_bits |= GL_COLOR_BUFFER_BIT;
4869 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4870 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4873 clear_bits |= GL_STENCIL_BUFFER_BIT;
4876 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4877 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4880 clear_bits |= GL_DEPTH_BUFFER_BIT;
4883 glDisable(GL_SCISSOR_TEST);
4884 glClear(clear_bits);
4886 framebuffer_manager()->MarkAttachmentsAsCleared(
4887 framebuffer, renderbuffer_manager(), texture_manager());
4889 RestoreClearState();
4891 if (target == GL_READ_FRAMEBUFFER_EXT) {
4892 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4893 Framebuffer* draw_framebuffer =
4894 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4895 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4896 GetBackbufferServiceId();
4897 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
4901 void GLES2DecoderImpl::RestoreClearState() {
4902 framebuffer_state_.clear_state_dirty = true;
4904 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4905 state_.color_clear_alpha);
4906 glClearStencil(state_.stencil_clear);
4907 glClearDepth(state_.depth_clear);
4908 if (state_.enable_flags.scissor_test) {
4909 glEnable(GL_SCISSOR_TEST);
4913 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
4914 Framebuffer* framebuffer =
4915 GetFramebufferInfoForTarget(target);
4917 return GL_FRAMEBUFFER_COMPLETE;
4919 GLenum completeness = framebuffer->IsPossiblyComplete();
4920 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4921 return completeness;
4923 return framebuffer->GetStatus(texture_manager(), target);
4926 void GLES2DecoderImpl::DoFramebufferTexture2D(
4927 GLenum target, GLenum attachment, GLenum textarget,
4928 GLuint client_texture_id, GLint level) {
4929 DoFramebufferTexture2DCommon(
4930 "glFramebufferTexture2D", target, attachment,
4931 textarget, client_texture_id, level, 0);
4934 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
4935 GLenum target, GLenum attachment, GLenum textarget,
4936 GLuint client_texture_id, GLint level, GLsizei samples) {
4937 if (!features().multisampled_render_to_texture) {
4939 GL_INVALID_OPERATION,
4940 "glFramebufferTexture2DMultisample", "function not available");
4943 DoFramebufferTexture2DCommon(
4944 "glFramebufferTexture2DMultisample", target, attachment,
4945 textarget, client_texture_id, level, samples);
4948 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
4949 const char* name, GLenum target, GLenum attachment, GLenum textarget,
4950 GLuint client_texture_id, GLint level, GLsizei samples) {
4951 if (samples > renderbuffer_manager()->max_samples()) {
4954 "glFramebufferTexture2DMultisample", "samples too large");
4957 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4960 GL_INVALID_OPERATION,
4961 name, "no framebuffer bound.");
4964 GLuint service_id = 0;
4965 TextureRef* texture_ref = NULL;
4966 if (client_texture_id) {
4967 texture_ref = GetTexture(client_texture_id);
4970 GL_INVALID_OPERATION,
4971 name, "unknown texture_ref");
4974 service_id = texture_ref->service_id();
4977 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
4980 name, "level out of range");
4985 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
4987 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
4989 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4991 if (features().use_img_for_multisampled_render_to_texture) {
4992 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
4993 service_id, level, samples);
4995 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
4996 service_id, level, samples);
4999 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5000 if (error == GL_NO_ERROR) {
5001 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5004 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5005 framebuffer_state_.clear_state_dirty = true;
5009 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5014 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5015 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5016 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5019 GL_INVALID_OPERATION,
5020 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5023 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5024 const Framebuffer::Attachment* attachment_object =
5025 framebuffer->GetAttachment(attachment);
5026 *params = attachment_object ? attachment_object->object_name() : 0;
5028 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5029 features().use_img_for_multisampled_render_to_texture) {
5030 pname = GL_TEXTURE_SAMPLES_IMG;
5032 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5036 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5037 GLenum target, GLenum pname, GLint* params) {
5038 Renderbuffer* renderbuffer =
5039 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5040 if (!renderbuffer) {
5042 GL_INVALID_OPERATION,
5043 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5047 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5048 *params = renderbuffer->internal_format();
5050 case GL_RENDERBUFFER_WIDTH:
5051 *params = renderbuffer->width();
5053 case GL_RENDERBUFFER_HEIGHT:
5054 *params = renderbuffer->height();
5056 case GL_RENDERBUFFER_SAMPLES_EXT:
5057 if (features().use_img_for_multisampled_render_to_texture) {
5058 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5061 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5065 glGetRenderbufferParameterivEXT(target, pname, params);
5070 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5071 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5072 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5073 GLbitfield mask, GLenum filter) {
5074 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5075 if (!features().chromium_framebuffer_multisample) {
5077 GL_INVALID_OPERATION,
5078 "glBlitFramebufferCHROMIUM", "function not available");
5082 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5086 glDisable(GL_SCISSOR_TEST);
5087 BlitFramebufferHelper(
5088 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5089 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
5092 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5093 const FeatureInfo* feature_info,
5096 GLenum internal_format,
5099 // TODO(sievers): This could be resolved at the GL binding level, but the
5100 // binding process is currently a bit too 'brute force'.
5101 if (feature_info->feature_flags().is_angle) {
5102 glRenderbufferStorageMultisampleANGLE(
5103 target, samples, internal_format, width, height);
5104 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5105 glRenderbufferStorageMultisample(
5106 target, samples, internal_format, width, height);
5108 glRenderbufferStorageMultisampleEXT(
5109 target, samples, internal_format, width, height);
5113 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5123 // TODO(sievers): This could be resolved at the GL binding level, but the
5124 // binding process is currently a bit too 'brute force'.
5125 if (feature_info_->feature_flags().is_angle) {
5126 glBlitFramebufferANGLE(
5127 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5128 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5130 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5132 glBlitFramebufferEXT(
5133 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5137 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5139 GLenum internalformat,
5142 if (samples > renderbuffer_manager()->max_samples()) {
5145 "glRenderbufferStorageMultisample", "samples too large");
5149 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5150 height > renderbuffer_manager()->max_renderbuffer_size()) {
5153 "glRenderbufferStorageMultisample", "dimensions too large");
5157 uint32 estimated_size = 0;
5158 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5159 width, height, samples, internalformat, &estimated_size)) {
5162 "glRenderbufferStorageMultisample", "dimensions too large");
5166 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5169 "glRenderbufferStorageMultisample", "out of memory");
5176 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5177 GLenum target, GLsizei samples, GLenum internalformat,
5178 GLsizei width, GLsizei height) {
5179 if (!features().chromium_framebuffer_multisample) {
5180 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5181 "glRenderbufferStorageMultisampleCHROMIUM",
5182 "function not available");
5186 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5187 if (!renderbuffer) {
5188 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5189 "glRenderbufferStorageMultisampleCHROMIUM",
5190 "no renderbuffer bound");
5194 if (!ValidateRenderbufferStorageMultisample(
5195 samples, internalformat, width, height)) {
5199 GLenum impl_format =
5200 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5202 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5203 "glRenderbufferStorageMultisampleCHROMIUM");
5204 RenderbufferStorageMultisampleHelper(
5205 feature_info_, target, samples, impl_format, width, height);
5207 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5208 if (error == GL_NO_ERROR) {
5210 if (workarounds().validate_multisample_buffer_allocation) {
5211 if (!VerifyMultisampleRenderbufferIntegrity(
5212 renderbuffer->service_id(), impl_format)) {
5215 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5220 // TODO(gman): If renderbuffers tracked which framebuffers they were
5221 // attached to we could just mark those framebuffers as not complete.
5222 framebuffer_manager()->IncFramebufferStateChangeCount();
5223 renderbuffer_manager()->SetInfo(
5224 renderbuffer, samples, internalformat, width, height);
5228 // This is the handler for multisampled_render_to_texture extensions.
5229 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5230 GLenum target, GLsizei samples, GLenum internalformat,
5231 GLsizei width, GLsizei height) {
5232 if (!features().multisampled_render_to_texture) {
5234 GL_INVALID_OPERATION,
5235 "glRenderbufferStorageMultisampleEXT", "function not available");
5239 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5240 if (!renderbuffer) {
5241 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5242 "glRenderbufferStorageMultisampleEXT",
5243 "no renderbuffer bound");
5247 if (!ValidateRenderbufferStorageMultisample(
5248 samples, internalformat, width, height)) {
5252 GLenum impl_format =
5253 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5255 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5256 if (features().use_img_for_multisampled_render_to_texture) {
5257 glRenderbufferStorageMultisampleIMG(
5258 target, samples, impl_format, width, height);
5260 glRenderbufferStorageMultisampleEXT(
5261 target, samples, impl_format, width, height);
5263 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5264 if (error == GL_NO_ERROR) {
5265 // TODO(gman): If renderbuffers tracked which framebuffers they were
5266 // attached to we could just mark those framebuffers as not complete.
5267 framebuffer_manager()->IncFramebufferStateChangeCount();
5268 renderbuffer_manager()->SetInfo(
5269 renderbuffer, samples, internalformat, width, height);
5273 // This function validates the allocation of a multisampled renderbuffer
5274 // by clearing it to a key color, blitting the contents to a texture, and
5275 // reading back the color to ensure it matches the key.
5276 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5277 GLuint renderbuffer, GLenum format) {
5279 // Only validate color buffers.
5280 // These formats have been selected because they are very common or are known
5281 // to be used by the WebGL backbuffer. If problems are observed with other
5282 // color formats they can be added here.
5293 GLint draw_framebuffer, read_framebuffer;
5295 // Cache framebuffer and texture bindings.
5296 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5297 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5299 if (!validation_texture_) {
5300 GLint bound_texture;
5301 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5303 // Create additional resources needed for the verification.
5304 glGenTextures(1, &validation_texture_);
5305 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5306 glGenFramebuffersEXT(1, &validation_fbo_);
5308 // Texture only needs to be 1x1.
5309 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5310 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5311 GL_UNSIGNED_BYTE, NULL);
5313 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5314 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5315 GL_TEXTURE_2D, validation_texture_, 0);
5317 glBindTexture(GL_TEXTURE_2D, bound_texture);
5320 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5321 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5322 GL_RENDERBUFFER, renderbuffer);
5324 // Cache current state and reset it to the values we require.
5325 GLboolean scissor_enabled = false;
5326 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5327 if (scissor_enabled)
5328 glDisable(GL_SCISSOR_TEST);
5330 GLboolean color_mask[4] = {true, true, true, true};
5331 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5332 glColorMask(true, true, true, true);
5334 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5335 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5336 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5338 // Clear the buffer to the desired key color.
5339 glClear(GL_COLOR_BUFFER_BIT);
5341 // Blit from the multisample buffer to a standard texture.
5342 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5343 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5345 BlitFramebufferHelper(
5346 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5348 // Read a pixel from the buffer.
5349 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5351 unsigned char pixel[3] = {0, 0, 0};
5352 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5354 // Detach the renderbuffer.
5355 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5356 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5357 GL_RENDERBUFFER, 0);
5359 // Restore cached state.
5360 if (scissor_enabled)
5361 glEnable(GL_SCISSOR_TEST);
5363 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5364 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5365 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5366 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5368 // Return true if the pixel matched the desired key color.
5369 return (pixel[0] == 0xFF &&
5374 void GLES2DecoderImpl::DoRenderbufferStorage(
5375 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5376 Renderbuffer* renderbuffer =
5377 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5378 if (!renderbuffer) {
5380 GL_INVALID_OPERATION,
5381 "glRenderbufferStorage", "no renderbuffer bound");
5385 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5386 height > renderbuffer_manager()->max_renderbuffer_size()) {
5388 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5392 uint32 estimated_size = 0;
5393 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5394 width, height, 1, internalformat, &estimated_size)) {
5396 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5400 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5402 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5406 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5407 glRenderbufferStorageEXT(
5409 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5413 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5414 if (error == GL_NO_ERROR) {
5415 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5416 // we could just mark those framebuffers as not complete.
5417 framebuffer_manager()->IncFramebufferStateChangeCount();
5418 renderbuffer_manager()->SetInfo(
5419 renderbuffer, 1, internalformat, width, height);
5423 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5424 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5425 Program* program = GetProgramInfoNotShader(
5426 program_id, "glLinkProgram");
5431 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5432 ShaderTranslator* vertex_translator = NULL;
5433 ShaderTranslator* fragment_translator = NULL;
5434 if (use_shader_translator_) {
5435 vertex_translator = vertex_translator_.get();
5436 fragment_translator = fragment_translator_.get();
5438 if (program->Link(shader_manager(),
5440 fragment_translator,
5441 workarounds().count_all_in_varyings_packing ?
5442 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5443 shader_cache_callback_)) {
5444 if (program == state_.current_program.get()) {
5445 if (workarounds().use_current_program_after_successful_link)
5446 glUseProgram(program->service_id());
5447 if (workarounds().clear_uniforms_before_first_program_use)
5448 program_manager()->ClearUniforms(program);
5453 void GLES2DecoderImpl::DoTexParameterf(
5454 GLenum target, GLenum pname, GLfloat param) {
5455 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5458 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5462 texture_manager()->SetParameter(
5463 "glTexParameterf", GetErrorState(), texture, pname,
5464 static_cast<GLint>(param));
5467 void GLES2DecoderImpl::DoTexParameteri(
5468 GLenum target, GLenum pname, GLint param) {
5469 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5472 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5476 texture_manager()->SetParameter(
5477 "glTexParameteri", GetErrorState(), texture, pname, param);
5480 void GLES2DecoderImpl::DoTexParameterfv(
5481 GLenum target, GLenum pname, const GLfloat* params) {
5482 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5485 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5489 texture_manager()->SetParameter(
5490 "glTexParameterfv", GetErrorState(), texture, pname,
5491 static_cast<GLint>(params[0]));
5494 void GLES2DecoderImpl::DoTexParameteriv(
5495 GLenum target, GLenum pname, const GLint* params) {
5496 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5500 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5504 texture_manager()->SetParameter(
5505 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5508 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5509 if (!state_.current_program.get()) {
5510 // The program does not exist.
5512 GL_INVALID_OPERATION, function_name, "no program in use");
5515 if (!state_.current_program->InUse()) {
5517 GL_INVALID_OPERATION, function_name, "program not linked");
5523 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5524 GLint location, const char* function_name) {
5525 if (!CheckCurrentProgram(function_name)) {
5528 return location != -1;
5533 static const GLenum valid_int_vec1_types_list[] = {
5537 GL_SAMPLER_2D_RECT_ARB,
5539 GL_SAMPLER_EXTERNAL_OES,
5542 static const GLenum valid_int_vec2_types_list[] = {
5547 static const GLenum valid_int_vec3_types_list[] = {
5552 static const GLenum valid_int_vec4_types_list[] = {
5557 static const GLenum valid_float_vec1_types_list[] = {
5562 static const GLenum valid_float_vec2_types_list[] = {
5567 static const GLenum valid_float_vec3_types_list[] = {
5572 static const GLenum valid_float_vec4_types_list[] = {
5577 static const GLenum valid_float_mat2_types_list[] = {
5581 static const GLenum valid_float_mat3_types_list[] = {
5585 static const GLenum valid_float_mat4_types_list[] = {
5589 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5590 valid_int_vec1_types_list,
5591 arraysize(valid_int_vec1_types_list),
5594 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5595 valid_int_vec2_types_list,
5596 arraysize(valid_int_vec2_types_list),
5599 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5600 valid_int_vec3_types_list,
5601 arraysize(valid_int_vec3_types_list),
5604 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5605 valid_int_vec4_types_list,
5606 arraysize(valid_int_vec4_types_list),
5609 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5610 valid_float_vec1_types_list,
5611 arraysize(valid_float_vec1_types_list),
5614 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5615 valid_float_vec2_types_list,
5616 arraysize(valid_float_vec2_types_list),
5619 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5620 valid_float_vec3_types_list,
5621 arraysize(valid_float_vec3_types_list),
5624 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5625 valid_float_vec4_types_list,
5626 arraysize(valid_float_vec4_types_list),
5629 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5630 valid_float_mat2_types_list,
5631 arraysize(valid_float_mat2_types_list),
5634 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5635 valid_float_mat3_types_list,
5636 arraysize(valid_float_mat3_types_list),
5639 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5640 valid_float_mat4_types_list,
5641 arraysize(valid_float_mat4_types_list),
5644 } // anonymous namespace.
5646 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5647 GLint fake_location, const char* function_name,
5648 const GLES2DecoderImpl::BaseUniformInfo& base_info,
5649 GLint* real_location, GLenum* type, GLsizei* count) {
5652 DCHECK(real_location);
5654 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5657 GLint array_index = -1;
5658 const Program::UniformInfo* info =
5659 state_.current_program->GetUniformInfoByFakeLocation(
5660 fake_location, real_location, &array_index);
5663 GL_INVALID_OPERATION, function_name, "unknown location");
5667 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5668 if (base_info.valid_types[ii] == info->type) {
5675 GL_INVALID_OPERATION, function_name,
5676 "wrong uniform function for type");
5679 if (*count > 1 && !info->is_array) {
5681 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5684 *count = std::min(info->size - array_index, *count);
5692 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5695 GLint real_location = -1;
5696 if (!PrepForSetUniformByLocation(
5697 fake_location, "glUniform1i", valid_int_vec1_base_info,
5698 &real_location, &type, &count)) {
5701 if (!state_.current_program->SetSamplers(
5702 state_.texture_units.size(), fake_location, 1, &v0)) {
5704 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5707 glUniform1i(real_location, v0);
5710 void GLES2DecoderImpl::DoUniform1iv(
5711 GLint fake_location, GLsizei count, const GLint *value) {
5713 GLint real_location = -1;
5714 if (!PrepForSetUniformByLocation(
5715 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5716 &real_location, &type, &count)) {
5719 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5720 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5721 if (!state_.current_program->SetSamplers(
5722 state_.texture_units.size(), fake_location, count, value)) {
5724 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5728 glUniform1iv(real_location, count, value);
5731 void GLES2DecoderImpl::DoUniform1fv(
5732 GLint fake_location, GLsizei count, const GLfloat* value) {
5734 GLint real_location = -1;
5735 if (!PrepForSetUniformByLocation(
5736 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5737 &real_location, &type, &count)) {
5740 if (type == GL_BOOL) {
5741 scoped_ptr<GLint[]> temp(new GLint[count]);
5742 for (GLsizei ii = 0; ii < count; ++ii) {
5743 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5745 DoUniform1iv(real_location, count, temp.get());
5747 glUniform1fv(real_location, count, value);
5751 void GLES2DecoderImpl::DoUniform2fv(
5752 GLint fake_location, GLsizei count, const GLfloat* value) {
5754 GLint real_location = -1;
5755 if (!PrepForSetUniformByLocation(
5756 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5757 &real_location, &type, &count)) {
5760 if (type == GL_BOOL_VEC2) {
5761 GLsizei num_values = count * 2;
5762 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5763 for (GLsizei ii = 0; ii < num_values; ++ii) {
5764 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5766 glUniform2iv(real_location, count, temp.get());
5768 glUniform2fv(real_location, count, value);
5772 void GLES2DecoderImpl::DoUniform3fv(
5773 GLint fake_location, GLsizei count, const GLfloat* value) {
5775 GLint real_location = -1;
5776 if (!PrepForSetUniformByLocation(
5777 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5778 &real_location, &type, &count)) {
5781 if (type == GL_BOOL_VEC3) {
5782 GLsizei num_values = count * 3;
5783 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5784 for (GLsizei ii = 0; ii < num_values; ++ii) {
5785 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5787 glUniform3iv(real_location, count, temp.get());
5789 glUniform3fv(real_location, count, value);
5793 void GLES2DecoderImpl::DoUniform4fv(
5794 GLint fake_location, GLsizei count, const GLfloat* value) {
5796 GLint real_location = -1;
5797 if (!PrepForSetUniformByLocation(
5798 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5799 &real_location, &type, &count)) {
5802 if (type == GL_BOOL_VEC4) {
5803 GLsizei num_values = count * 4;
5804 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5805 for (GLsizei ii = 0; ii < num_values; ++ii) {
5806 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5808 glUniform4iv(real_location, count, temp.get());
5810 glUniform4fv(real_location, count, value);
5814 void GLES2DecoderImpl::DoUniform2iv(
5815 GLint fake_location, GLsizei count, const GLint* value) {
5817 GLint real_location = -1;
5818 if (!PrepForSetUniformByLocation(
5819 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5820 &real_location, &type, &count)) {
5823 glUniform2iv(real_location, count, value);
5826 void GLES2DecoderImpl::DoUniform3iv(
5827 GLint fake_location, GLsizei count, const GLint* value) {
5829 GLint real_location = -1;
5830 if (!PrepForSetUniformByLocation(
5831 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5832 &real_location, &type, &count)) {
5835 glUniform3iv(real_location, count, value);
5838 void GLES2DecoderImpl::DoUniform4iv(
5839 GLint fake_location, GLsizei count, const GLint* value) {
5841 GLint real_location = -1;
5842 if (!PrepForSetUniformByLocation(
5843 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5844 &real_location, &type, &count)) {
5847 glUniform4iv(real_location, count, value);
5850 void GLES2DecoderImpl::DoUniformMatrix2fv(
5851 GLint fake_location, GLsizei count, GLboolean transpose,
5852 const GLfloat* value) {
5854 GLint real_location = -1;
5855 if (!PrepForSetUniformByLocation(
5856 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5857 &real_location, &type, &count)) {
5860 glUniformMatrix2fv(real_location, count, transpose, value);
5863 void GLES2DecoderImpl::DoUniformMatrix3fv(
5864 GLint fake_location, GLsizei count, GLboolean transpose,
5865 const GLfloat* value) {
5867 GLint real_location = -1;
5868 if (!PrepForSetUniformByLocation(
5869 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5870 &real_location, &type, &count)) {
5873 glUniformMatrix3fv(real_location, count, transpose, value);
5876 void GLES2DecoderImpl::DoUniformMatrix4fv(
5877 GLint fake_location, GLsizei count, GLboolean transpose,
5878 const GLfloat* value) {
5880 GLint real_location = -1;
5881 if (!PrepForSetUniformByLocation(
5882 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5883 &real_location, &type, &count)) {
5886 glUniformMatrix4fv(real_location, count, transpose, value);
5889 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5890 GLuint service_id = 0;
5891 Program* program = NULL;
5893 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5897 if (!program->IsValid()) {
5898 // Program was not linked successfully. (ie, glLinkProgram)
5900 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5903 service_id = program->service_id();
5905 if (state_.current_program.get()) {
5906 program_manager()->UnuseProgram(shader_manager(),
5907 state_.current_program.get());
5909 state_.current_program = program;
5910 LogClientServiceMapping("glUseProgram", program_id, service_id);
5911 glUseProgram(service_id);
5912 if (state_.current_program.get()) {
5913 program_manager()->UseProgram(state_.current_program.get());
5914 if (workarounds().clear_uniforms_before_first_program_use)
5915 program_manager()->ClearUniforms(program);
5919 void GLES2DecoderImpl::RenderWarning(
5920 const char* filename, int line, const std::string& msg) {
5921 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
5924 void GLES2DecoderImpl::PerformanceWarning(
5925 const char* filename, int line, const std::string& msg) {
5926 logger_.LogMessage(filename, line,
5927 std::string("PERFORMANCE WARNING: ") + msg);
5930 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5931 Texture* texture, GLenum textarget) {
5932 // Image is already in use if texture is attached to a framebuffer.
5933 if (texture && !texture->IsAttachedToFramebuffer()) {
5934 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5936 ScopedGLErrorSuppressor suppressor(
5937 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5939 glBindTexture(textarget, texture->service_id());
5940 image->WillUseTexImage();
5941 RestoreCurrentTextureBindings(&state_, textarget);
5946 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
5947 Texture* texture, GLenum textarget) {
5948 // Image is still in use if texture is attached to a framebuffer.
5949 if (texture && !texture->IsAttachedToFramebuffer()) {
5950 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5952 ScopedGLErrorSuppressor suppressor(
5953 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
5955 glBindTexture(textarget, texture->service_id());
5956 image->DidUseTexImage();
5957 RestoreCurrentTextureBindings(&state_, textarget);
5962 bool GLES2DecoderImpl::PrepareTexturesForRender() {
5963 DCHECK(state_.current_program.get());
5964 if (!texture_manager()->HaveUnrenderableTextures() &&
5965 !texture_manager()->HaveImages()) {
5969 bool textures_set = false;
5970 const Program::SamplerIndices& sampler_indices =
5971 state_.current_program->sampler_indices();
5972 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5973 const Program::UniformInfo* uniform_info =
5974 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5975 DCHECK(uniform_info);
5976 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5977 GLuint texture_unit_index = uniform_info->texture_units[jj];
5978 if (texture_unit_index < state_.texture_units.size()) {
5979 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5980 TextureRef* texture_ref =
5981 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5982 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
5983 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
5984 textures_set = true;
5985 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5988 texture_manager()->black_texture_id(uniform_info->type));
5989 LOCAL_RENDER_WARNING(
5990 std::string("texture bound to texture unit ") +
5991 base::IntToString(texture_unit_index) +
5992 " is not renderable. It maybe non-power-of-2 and have"
5993 " incompatible texture filtering or is not"
5994 " 'texture complete'");
5998 if (textarget != GL_TEXTURE_CUBE_MAP) {
5999 Texture* texture = texture_ref->texture();
6000 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6001 if (image && !texture->IsAttachedToFramebuffer()) {
6002 ScopedGLErrorSuppressor suppressor(
6003 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6004 textures_set = true;
6005 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6006 image->WillUseTexImage();
6011 // else: should this be an error?
6014 return !textures_set;
6017 void GLES2DecoderImpl::RestoreStateForTextures() {
6018 DCHECK(state_.current_program.get());
6019 const Program::SamplerIndices& sampler_indices =
6020 state_.current_program->sampler_indices();
6021 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6022 const Program::UniformInfo* uniform_info =
6023 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6024 DCHECK(uniform_info);
6025 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6026 GLuint texture_unit_index = uniform_info->texture_units[jj];
6027 if (texture_unit_index < state_.texture_units.size()) {
6028 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6029 TextureRef* texture_ref =
6030 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6031 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6032 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6033 // Get the texture_ref info that was previously bound here.
6034 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6035 ? texture_unit.bound_texture_2d.get()
6036 : texture_unit.bound_texture_cube_map.get();
6037 glBindTexture(texture_unit.bind_target,
6038 texture_ref ? texture_ref->service_id() : 0);
6042 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6043 Texture* texture = texture_ref->texture();
6044 gfx::GLImage* image =
6045 texture->GetLevelImage(texture_unit.bind_target, 0);
6046 if (image && !texture->IsAttachedToFramebuffer()) {
6047 ScopedGLErrorSuppressor suppressor(
6048 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6049 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6050 image->DidUseTexImage();
6057 // Set the active texture back to whatever the user had it as.
6058 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6061 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6062 // Only check if there are some uncleared textures.
6063 if (!texture_manager()->HaveUnsafeTextures()) {
6067 // 1: Check all textures we are about to render with.
6068 if (state_.current_program.get()) {
6069 const Program::SamplerIndices& sampler_indices =
6070 state_.current_program->sampler_indices();
6071 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6072 const Program::UniformInfo* uniform_info =
6073 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6074 DCHECK(uniform_info);
6075 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6076 GLuint texture_unit_index = uniform_info->texture_units[jj];
6077 if (texture_unit_index < state_.texture_units.size()) {
6078 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6079 TextureRef* texture_ref =
6080 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6081 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6082 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6093 bool GLES2DecoderImpl::IsDrawValid(
6094 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
6095 // NOTE: We specifically do not check current_program->IsValid() because
6096 // it could never be invalid since glUseProgram would have failed. While
6097 // glLinkProgram could later mark the program as invalid the previous
6098 // valid program will still function if it is still the current program.
6099 if (!state_.current_program.get()) {
6100 // The program does not exist.
6101 // But GL says no ERROR.
6102 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6106 return state_.vertex_attrib_manager
6107 ->ValidateBindings(function_name,
6109 feature_info_.get(),
6110 state_.current_program.get(),
6111 max_vertex_accessed,
6115 bool GLES2DecoderImpl::SimulateAttrib0(
6116 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6120 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6123 const VertexAttrib* attrib =
6124 state_.vertex_attrib_manager->GetVertexAttrib(0);
6125 // If it's enabled or it's not used then we don't need to do anything.
6126 bool attrib_0_used =
6127 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6128 if (attrib->enabled() && attrib_0_used) {
6132 // Make a buffer with a single repeated vec4 value enough to
6133 // simulate the constant value that is supposed to be here.
6134 // This is required to emulate GLES2 on GL.
6135 GLuint num_vertices = max_vertex_accessed + 1;
6136 uint32 size_needed = 0;
6138 if (num_vertices == 0 ||
6139 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6140 size_needed > 0x7FFFFFFFU) {
6141 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6145 LOCAL_PERFORMANCE_WARNING(
6146 "Attribute 0 is disabled. This has signficant performance penalty");
6148 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6149 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6151 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6153 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6154 GLenum error = glGetError();
6155 if (error != GL_NO_ERROR) {
6157 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6162 const Vec4& value = state_.attrib_values[0];
6165 (!attrib_0_buffer_matches_value_ ||
6166 (value.v[0] != attrib_0_value_.v[0] ||
6167 value.v[1] != attrib_0_value_.v[1] ||
6168 value.v[2] != attrib_0_value_.v[2] ||
6169 value.v[3] != attrib_0_value_.v[3])))) {
6170 std::vector<Vec4> temp(num_vertices, value);
6171 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6172 attrib_0_buffer_matches_value_ = true;
6173 attrib_0_value_ = value;
6174 attrib_0_size_ = size_needed;
6177 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6179 if (attrib->divisor())
6180 glVertexAttribDivisorANGLE(0, 0);
6186 void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
6187 const VertexAttrib* attrib =
6188 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6189 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6190 Buffer* buffer = attrib->buffer();
6191 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6192 glVertexAttribPointer(
6193 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6194 attrib->gl_stride(), ptr);
6195 if (attrib->divisor())
6196 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6199 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6202 // Never touch vertex attribute 0's state (in particular, never
6203 // disable it) when running on desktop GL because it will never be
6205 if (attrib_index != 0 ||
6206 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6207 if (attrib->enabled()) {
6208 glEnableVertexAttribArray(attrib_index);
6210 glDisableVertexAttribArray(attrib_index);
6215 bool GLES2DecoderImpl::SimulateFixedAttribs(
6216 const char* function_name,
6217 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6220 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6223 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6227 LOCAL_PERFORMANCE_WARNING(
6228 "GL_FIXED attributes have a signficant performance penalty");
6230 // NOTE: we could be smart and try to check if a buffer is used
6231 // twice in 2 different attribs, find the overlapping parts and therefore
6232 // duplicate the minimum amount of data but this whole code path is not meant
6233 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6234 // tests so we just add to the buffer attrib used.
6236 GLuint elements_needed = 0;
6237 const VertexAttribManager::VertexAttribList& enabled_attribs =
6238 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6239 for (VertexAttribManager::VertexAttribList::const_iterator it =
6240 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6241 const VertexAttrib* attrib = *it;
6242 const Program::VertexAttrib* attrib_info =
6243 state_.current_program->GetAttribInfoByLocation(attrib->index());
6244 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6245 max_vertex_accessed);
6246 GLuint num_vertices = max_accessed + 1;
6247 if (num_vertices == 0) {
6249 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6253 attrib->CanAccess(max_accessed) &&
6254 attrib->type() == GL_FIXED) {
6255 uint32 elements_used = 0;
6256 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6257 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6259 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6265 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6266 uint32 size_needed = 0;
6267 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6268 size_needed > 0x7FFFFFFFU) {
6270 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6274 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6276 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6277 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6278 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6279 GLenum error = glGetError();
6280 if (error != GL_NO_ERROR) {
6282 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6287 // Copy the elements and convert to float
6288 GLintptr offset = 0;
6289 for (VertexAttribManager::VertexAttribList::const_iterator it =
6290 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6291 const VertexAttrib* attrib = *it;
6292 const Program::VertexAttrib* attrib_info =
6293 state_.current_program->GetAttribInfoByLocation(attrib->index());
6294 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6295 max_vertex_accessed);
6296 GLuint num_vertices = max_accessed + 1;
6297 if (num_vertices == 0) {
6299 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6303 attrib->CanAccess(max_accessed) &&
6304 attrib->type() == GL_FIXED) {
6305 int num_elements = attrib->size() * kSizeOfFloat;
6306 int size = num_elements * num_vertices;
6307 scoped_ptr<float[]> data(new float[size]);
6308 const int32* src = reinterpret_cast<const int32 *>(
6309 attrib->buffer()->GetRange(attrib->offset(), size));
6310 const int32* end = src + num_elements;
6311 float* dst = data.get();
6312 while (src != end) {
6313 *dst++ = static_cast<float>(*src++) / 65536.0f;
6315 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6316 glVertexAttribPointer(
6317 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6318 reinterpret_cast<GLvoid*>(offset));
6326 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6327 // There's no need to call glVertexAttribPointer because we shadow all the
6328 // settings and passing GL_FIXED to it will not work.
6331 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6335 error::Error GLES2DecoderImpl::DoDrawArrays(
6336 const char* function_name,
6341 GLsizei primcount) {
6342 error::Error error = WillAccessBoundFramebufferForDraw();
6343 if (error != error::kNoError)
6345 if (!validators_->draw_mode.IsValid(mode)) {
6346 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6347 return error::kNoError;
6350 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6351 return error::kNoError;
6353 if (primcount < 0) {
6354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6355 return error::kNoError;
6357 if (!CheckBoundFramebuffersValid(function_name)) {
6358 return error::kNoError;
6360 // We have to check this here because the prototype for glDrawArrays
6361 // is GLint not GLsizei.
6363 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6364 return error::kNoError;
6367 if (count == 0 || (instanced && primcount == 0)) {
6368 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6369 return error::kNoError;
6372 GLuint max_vertex_accessed = first + count - 1;
6373 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6374 if (!ClearUnclearedTextures()) {
6375 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6376 return error::kNoError;
6378 bool simulated_attrib_0 = false;
6379 if (!SimulateAttrib0(
6380 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6381 return error::kNoError;
6383 bool simulated_fixed_attribs = false;
6384 if (SimulateFixedAttribs(
6385 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6387 bool textures_set = !PrepareTexturesForRender();
6390 glDrawArrays(mode, first, count);
6392 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6394 ProcessPendingQueries();
6396 RestoreStateForTextures();
6398 if (simulated_fixed_attribs) {
6399 RestoreStateForSimulatedFixedAttribs();
6402 if (simulated_attrib_0) {
6403 RestoreStateForAttrib(0);
6406 return error::kNoError;
6409 error::Error GLES2DecoderImpl::HandleDrawArrays(
6410 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6411 return DoDrawArrays("glDrawArrays",
6413 static_cast<GLenum>(c.mode),
6414 static_cast<GLint>(c.first),
6415 static_cast<GLsizei>(c.count),
6419 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6420 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6421 if (!features().angle_instanced_arrays) {
6423 GL_INVALID_OPERATION,
6424 "glDrawArraysInstancedANGLE", "function not available");
6425 return error::kNoError;
6427 return DoDrawArrays("glDrawArraysIntancedANGLE",
6429 static_cast<GLenum>(c.mode),
6430 static_cast<GLint>(c.first),
6431 static_cast<GLsizei>(c.count),
6432 static_cast<GLsizei>(c.primcount));
6435 error::Error GLES2DecoderImpl::DoDrawElements(
6436 const char* function_name,
6442 GLsizei primcount) {
6443 error::Error error = WillAccessBoundFramebufferForDraw();
6444 if (error != error::kNoError)
6446 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6448 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6449 return error::kNoError;
6453 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6454 return error::kNoError;
6457 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6458 return error::kNoError;
6460 if (!validators_->draw_mode.IsValid(mode)) {
6461 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6462 return error::kNoError;
6464 if (!validators_->index_type.IsValid(type)) {
6465 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6466 return error::kNoError;
6468 if (primcount < 0) {
6469 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6470 return error::kNoError;
6473 if (!CheckBoundFramebuffersValid(function_name)) {
6474 return error::kNoError;
6477 if (count == 0 || (instanced && primcount == 0)) {
6478 return error::kNoError;
6481 GLuint max_vertex_accessed;
6482 Buffer* element_array_buffer =
6483 state_.vertex_attrib_manager->element_array_buffer();
6485 if (!element_array_buffer->GetMaxValueForRange(
6486 offset, count, type, &max_vertex_accessed)) {
6488 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6489 return error::kNoError;
6492 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6493 if (!ClearUnclearedTextures()) {
6494 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6495 return error::kNoError;
6497 bool simulated_attrib_0 = false;
6498 if (!SimulateAttrib0(
6499 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6500 return error::kNoError;
6502 bool simulated_fixed_attribs = false;
6503 if (SimulateFixedAttribs(
6504 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6506 bool textures_set = !PrepareTexturesForRender();
6508 // TODO(gman): Refactor to hide these details in BufferManager or
6509 // VertexAttribManager.
6510 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6511 bool used_client_side_array = false;
6512 if (element_array_buffer->IsClientSideArray()) {
6513 used_client_side_array = true;
6514 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6515 indices = element_array_buffer->GetRange(offset, 0);
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::DoGetVertexAttribfv(
6864 GLuint index, GLenum pname, GLfloat* params) {
6865 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6868 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6872 case GL_CURRENT_VERTEX_ATTRIB: {
6873 const Vec4& value = state_.attrib_values[index];
6874 params[0] = value.v[0];
6875 params[1] = value.v[1];
6876 params[2] = value.v[2];
6877 params[3] = value.v[3];
6882 GetVertexAttribHelper(attrib, pname, &value);
6883 *params = static_cast<GLfloat>(value);
6889 void GLES2DecoderImpl::DoGetVertexAttribiv(
6890 GLuint index, GLenum pname, GLint* params) {
6891 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6894 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6898 case GL_CURRENT_VERTEX_ATTRIB: {
6899 const Vec4& value = state_.attrib_values[index];
6900 params[0] = static_cast<GLint>(value.v[0]);
6901 params[1] = static_cast<GLint>(value.v[1]);
6902 params[2] = static_cast<GLint>(value.v[2]);
6903 params[3] = static_cast<GLint>(value.v[3]);
6907 GetVertexAttribHelper(attrib, pname, params);
6912 bool GLES2DecoderImpl::SetVertexAttribValue(
6913 const char* function_name, GLuint index, const GLfloat* value) {
6914 if (index >= state_.attrib_values.size()) {
6915 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
6918 Vec4& v = state_.attrib_values[index];
6926 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6927 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6928 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6929 glVertexAttrib1f(index, v0);
6933 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
6934 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6935 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6936 glVertexAttrib2f(index, v0, v1);
6940 void GLES2DecoderImpl::DoVertexAttrib3f(
6941 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
6942 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6943 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6944 glVertexAttrib3f(index, v0, v1, v2);
6948 void GLES2DecoderImpl::DoVertexAttrib4f(
6949 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
6950 GLfloat v[4] = { v0, v1, v2, v3, };
6951 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6952 glVertexAttrib4f(index, v0, v1, v2, v3);
6956 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
6957 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6958 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6959 glVertexAttrib1fv(index, v);
6963 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
6964 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6965 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6966 glVertexAttrib2fv(index, v);
6970 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
6971 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6972 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6973 glVertexAttrib3fv(index, v);
6977 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
6978 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6979 glVertexAttrib4fv(index, v);
6983 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
6984 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
6986 if (!state_.bound_array_buffer.get() ||
6987 state_.bound_array_buffer->IsDeleted()) {
6988 if (state_.vertex_attrib_manager.get() ==
6989 default_vertex_attrib_manager_.get()) {
6991 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
6992 return error::kNoError;
6993 } else if (c.offset != 0) {
6996 "glVertexAttribPointer", "client side arrays are not allowed");
6997 return error::kNoError;
7001 GLuint indx = c.indx;
7002 GLint size = c.size;
7003 GLenum type = c.type;
7004 GLboolean normalized = c.normalized;
7005 GLsizei stride = c.stride;
7006 GLsizei offset = c.offset;
7007 const void* ptr = reinterpret_cast<const void*>(offset);
7008 if (!validators_->vertex_attrib_type.IsValid(type)) {
7009 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7010 return error::kNoError;
7012 if (!validators_->vertex_attrib_size.IsValid(size)) {
7014 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7015 return error::kNoError;
7017 if (indx >= group_->max_vertex_attribs()) {
7019 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7020 return error::kNoError;
7024 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7025 return error::kNoError;
7029 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7030 return error::kNoError;
7034 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7035 return error::kNoError;
7037 GLsizei component_size =
7038 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7039 if (offset % component_size > 0) {
7041 GL_INVALID_OPERATION,
7042 "glVertexAttribPointer", "offset not valid for type");
7043 return error::kNoError;
7045 if (stride % component_size > 0) {
7047 GL_INVALID_OPERATION,
7048 "glVertexAttribPointer", "stride not valid for type");
7049 return error::kNoError;
7051 state_.vertex_attrib_manager
7052 ->SetAttribInfo(indx,
7053 state_.bound_array_buffer.get(),
7058 stride != 0 ? stride : component_size * size,
7060 if (type != GL_FIXED) {
7061 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7063 return error::kNoError;
7066 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7068 state_.viewport_x = x;
7069 state_.viewport_y = y;
7070 state_.viewport_width = std::min(width, viewport_max_width_);
7071 state_.viewport_height = std::min(height, viewport_max_height_);
7072 glViewport(x, y, width, height);
7075 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7076 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7077 if (!features().angle_instanced_arrays) {
7079 GL_INVALID_OPERATION,
7080 "glVertexAttribDivisorANGLE", "function not available");
7082 GLuint index = c.index;
7083 GLuint divisor = c.divisor;
7084 if (index >= group_->max_vertex_attribs()) {
7087 "glVertexAttribDivisorANGLE", "index out of range");
7088 return error::kNoError;
7091 state_.vertex_attrib_manager->SetDivisor(
7094 glVertexAttribDivisorANGLE(index, divisor);
7095 return error::kNoError;
7098 template <typename pixel_data_type>
7099 static void WriteAlphaData(
7100 void *pixels, uint32 row_count, uint32 channel_count,
7101 uint32 alpha_channel_index, uint32 unpadded_row_size,
7102 uint32 padded_row_size, pixel_data_type alpha_value) {
7103 DCHECK_GT(channel_count, 0U);
7104 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7105 uint32 unpadded_row_size_in_elements =
7106 unpadded_row_size / sizeof(pixel_data_type);
7107 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7108 uint32 padded_row_size_in_elements =
7109 padded_row_size / sizeof(pixel_data_type);
7110 pixel_data_type* dst =
7111 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7112 for (uint32 yy = 0; yy < row_count; ++yy) {
7113 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7114 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7117 dst += padded_row_size_in_elements;
7121 void GLES2DecoderImpl::FinishReadPixels(
7122 const cmds::ReadPixels& c,
7124 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7125 GLsizei width = c.width;
7126 GLsizei height = c.height;
7127 GLenum format = c.format;
7128 GLenum type = c.type;
7129 typedef cmds::ReadPixels::Result Result;
7131 Result* result = NULL;
7132 if (c.result_shm_id != 0) {
7133 result = GetSharedMemoryAs<Result*>(
7134 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7137 glDeleteBuffersARB(1, &buffer);
7142 GLES2Util::ComputeImageDataSizes(
7143 width, height, format, type, state_.pack_alignment, &pixels_size,
7145 void* pixels = GetSharedMemoryAs<void*>(
7146 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7149 glDeleteBuffersARB(1, &buffer);
7155 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7157 if (features().map_buffer_range) {
7158 data = glMapBufferRange(
7159 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7161 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7163 memcpy(pixels, data, pixels_size);
7164 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7165 // have to restore the state.
7166 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7167 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7168 glDeleteBuffersARB(1, &buffer);
7171 if (result != NULL) {
7175 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7176 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7177 if ((channels_exist & 0x0008) == 0 &&
7178 workarounds().clear_alpha_in_readpixels) {
7179 // Set the alpha to 255 because some drivers are buggy in this regard.
7182 uint32 unpadded_row_size;
7183 uint32 padded_row_size;
7184 if (!GLES2Util::ComputeImageDataSizes(
7185 width, 2, format, type, state_.pack_alignment, &temp_size,
7186 &unpadded_row_size, &padded_row_size)) {
7190 uint32 channel_count = 0;
7191 uint32 alpha_channel = 0;
7204 if (channel_count > 0) {
7206 case GL_UNSIGNED_BYTE:
7207 WriteAlphaData<uint8>(
7208 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7209 padded_row_size, 0xFF);
7212 WriteAlphaData<float>(
7213 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7214 padded_row_size, 1.0f);
7217 WriteAlphaData<uint16>(
7218 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7219 padded_row_size, 0x3C00);
7227 error::Error GLES2DecoderImpl::HandleReadPixels(
7228 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7229 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7230 if (fbo_error != error::kNoError)
7234 GLsizei width = c.width;
7235 GLsizei height = c.height;
7236 GLenum format = c.format;
7237 GLenum type = c.type;
7238 GLboolean async = c.async;
7239 if (width < 0 || height < 0) {
7240 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7241 return error::kNoError;
7243 typedef cmds::ReadPixels::Result Result;
7245 if (!GLES2Util::ComputeImageDataSizes(
7246 width, height, format, type, state_.pack_alignment, &pixels_size,
7248 return error::kOutOfBounds;
7250 void* pixels = GetSharedMemoryAs<void*>(
7251 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7253 return error::kOutOfBounds;
7255 Result* result = NULL;
7256 if (c.result_shm_id != 0) {
7257 result = GetSharedMemoryAs<Result*>(
7258 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7260 return error::kOutOfBounds;
7264 if (!validators_->read_pixel_format.IsValid(format)) {
7265 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7266 return error::kNoError;
7268 if (!validators_->read_pixel_type.IsValid(type)) {
7269 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7270 return error::kNoError;
7272 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7273 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7274 // format and type are acceptable enums but not guaranteed to be supported
7275 // for this framebuffer. Have to ask gl if they are valid.
7276 GLint preferred_format = 0;
7277 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7278 GLint preferred_type = 0;
7279 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7280 if (format != static_cast<GLenum>(preferred_format) ||
7281 type != static_cast<GLenum>(preferred_type)) {
7283 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7284 "with the current read framebuffer");
7285 return error::kNoError;
7288 if (width == 0 || height == 0) {
7289 return error::kNoError;
7292 // Get the size of the current fbo or backbuffer.
7293 gfx::Size max_size = GetBoundReadFrameBufferSize();
7297 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7299 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7300 return error::kNoError;
7303 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7304 return error::kNoError;
7307 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7309 ScopedResolvedFrameBufferBinder binder(this, false, true);
7311 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7312 // The user requested an out of range area. Get the results 1 line
7315 uint32 unpadded_row_size;
7316 uint32 padded_row_size;
7317 if (!GLES2Util::ComputeImageDataSizes(
7318 width, 2, format, type, state_.pack_alignment, &temp_size,
7319 &unpadded_row_size, &padded_row_size)) {
7321 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7322 return error::kNoError;
7325 GLint dest_x_offset = std::max(-x, 0);
7326 uint32 dest_row_offset;
7327 if (!GLES2Util::ComputeImageDataSizes(
7328 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7331 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7332 return error::kNoError;
7335 // Copy each row into the larger dest rect.
7336 int8* dst = static_cast<int8*>(pixels);
7337 GLint read_x = std::max(0, x);
7338 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7339 GLint read_width = read_end_x - read_x;
7340 for (GLint yy = 0; yy < height; ++yy) {
7344 memset(dst, 0, unpadded_row_size);
7346 // If the row is in range, copy it.
7347 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7349 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7351 dst += padded_row_size;
7354 if (async && features().use_async_readpixels) {
7356 glGenBuffersARB(1, &buffer);
7357 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7358 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7359 GLenum error = glGetError();
7360 if (error == GL_NO_ERROR) {
7361 glReadPixels(x, y, width, height, format, type, 0);
7362 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7363 new FenceCallback()));
7364 WaitForReadPixels(base::Bind(
7365 &GLES2DecoderImpl::FinishReadPixels,
7366 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7367 <GLES2DecoderImpl>(this),
7369 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7370 return error::kNoError;
7373 glReadPixels(x, y, width, height, format, type, pixels);
7375 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7376 if (error == GL_NO_ERROR) {
7377 if (result != NULL) {
7380 FinishReadPixels(c, 0);
7383 return error::kNoError;
7386 error::Error GLES2DecoderImpl::HandlePixelStorei(
7387 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7388 GLenum pname = c.pname;
7389 GLenum param = c.param;
7390 if (!validators_->pixel_store.IsValid(pname)) {
7391 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7392 return error::kNoError;
7395 case GL_PACK_ALIGNMENT:
7396 case GL_UNPACK_ALIGNMENT:
7397 if (!validators_->pixel_store_alignment.IsValid(param)) {
7399 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7400 return error::kNoError;
7403 case GL_UNPACK_FLIP_Y_CHROMIUM:
7404 unpack_flip_y_ = (param != 0);
7405 return error::kNoError;
7406 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7407 unpack_premultiply_alpha_ = (param != 0);
7408 return error::kNoError;
7409 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7410 unpack_unpremultiply_alpha_ = (param != 0);
7411 return error::kNoError;
7415 glPixelStorei(pname, param);
7417 case GL_PACK_ALIGNMENT:
7418 state_.pack_alignment = param;
7420 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7421 state_.pack_reverse_row_order = (param != 0);
7423 case GL_UNPACK_ALIGNMENT:
7424 state_.unpack_alignment = param;
7427 // Validation should have prevented us from getting here.
7431 return error::kNoError;
7434 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7435 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7436 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7437 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
7439 GL_INVALID_OPERATION,
7440 "glPostSubBufferCHROMIUM", "command not supported by surface");
7441 return error::kNoError;
7444 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7447 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7448 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7449 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7450 is_offscreen ? offscreen_size_ : surface_->GetSize());
7452 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7453 return error::kNoError;
7455 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7456 return error::kLostContext;
7460 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7461 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7462 const std::string& name_str) {
7463 if (!StringIsValidForGLES(name_str.c_str())) {
7465 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7466 return error::kNoError;
7468 Program* program = GetProgramInfoNotShader(
7469 client_id, "glGetAttribLocation");
7471 return error::kNoError;
7473 if (!program->IsValid()) {
7475 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7476 return error::kNoError;
7478 GLint* location = GetSharedMemoryAs<GLint*>(
7479 location_shm_id, location_shm_offset, sizeof(GLint));
7481 return error::kOutOfBounds;
7483 // Require the client to init this incase the context is lost and we are no
7484 // longer executing commands.
7485 if (*location != -1) {
7486 return error::kGenericError;
7488 *location = program->GetAttribLocation(name_str);
7489 return error::kNoError;
7492 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7493 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7494 uint32 name_size = c.data_size;
7495 const char* name = GetSharedMemoryAs<const char*>(
7496 c.name_shm_id, c.name_shm_offset, name_size);
7498 return error::kOutOfBounds;
7500 String name_str(name, name_size);
7501 return GetAttribLocationHelper(
7502 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7505 error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
7506 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
7507 Bucket* bucket = GetBucket(c.name_bucket_id);
7509 return error::kInvalidArguments;
7511 std::string name_str;
7512 if (!bucket->GetAsString(&name_str)) {
7513 return error::kInvalidArguments;
7515 return GetAttribLocationHelper(
7516 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7519 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7520 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7521 const std::string& name_str) {
7522 if (!StringIsValidForGLES(name_str.c_str())) {
7524 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7525 return error::kNoError;
7527 Program* program = GetProgramInfoNotShader(
7528 client_id, "glGetUniformLocation");
7530 return error::kNoError;
7532 if (!program->IsValid()) {
7534 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7535 return error::kNoError;
7537 GLint* location = GetSharedMemoryAs<GLint*>(
7538 location_shm_id, location_shm_offset, sizeof(GLint));
7540 return error::kOutOfBounds;
7542 // Require the client to init this incase the context is lost an we are no
7543 // longer executing commands.
7544 if (*location != -1) {
7545 return error::kGenericError;
7547 *location = program->GetUniformFakeLocation(name_str);
7548 return error::kNoError;
7551 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7552 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7553 uint32 name_size = c.data_size;
7554 const char* name = GetSharedMemoryAs<const char*>(
7555 c.name_shm_id, c.name_shm_offset, name_size);
7557 return error::kOutOfBounds;
7559 String name_str(name, name_size);
7560 return GetUniformLocationHelper(
7561 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7564 error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
7565 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
7566 Bucket* bucket = GetBucket(c.name_bucket_id);
7568 return error::kInvalidArguments;
7570 std::string name_str;
7571 if (!bucket->GetAsString(&name_str)) {
7572 return error::kInvalidArguments;
7574 return GetUniformLocationHelper(
7575 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7578 error::Error GLES2DecoderImpl::HandleGetString(
7579 uint32 immediate_data_size, const cmds::GetString& c) {
7580 GLenum name = static_cast<GLenum>(c.name);
7581 if (!validators_->string_type.IsValid(name)) {
7582 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7583 return error::kNoError;
7585 const char* str = reinterpret_cast<const char*>(glGetString(name));
7586 std::string extensions;
7589 str = "OpenGL ES 2.0 Chromium";
7591 case GL_SHADING_LANGUAGE_VERSION:
7592 str = "OpenGL ES GLSL ES 1.0 Chromium";
7596 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7597 // They are used by WEBGL_debug_renderer_info.
7598 if (!force_webgl_glsl_validation_)
7603 // For WebGL contexts, strip out the OES derivatives and
7604 // EXT frag depth extensions if they have not been enabled.
7605 if (force_webgl_glsl_validation_) {
7606 extensions = feature_info_->extensions();
7607 if (!derivatives_explicitly_enabled_) {
7608 size_t offset = extensions.find(kOESDerivativeExtension);
7609 if (std::string::npos != offset) {
7610 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7614 if (!frag_depth_explicitly_enabled_) {
7615 size_t offset = extensions.find(kEXTFragDepthExtension);
7616 if (std::string::npos != offset) {
7617 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7621 if (!draw_buffers_explicitly_enabled_) {
7622 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7623 if (std::string::npos != offset) {
7624 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7629 extensions = feature_info_->extensions().c_str();
7631 std::string surface_extensions = surface_->GetExtensions();
7632 if (!surface_extensions.empty())
7633 extensions += " " + surface_extensions;
7634 str = extensions.c_str();
7640 Bucket* bucket = CreateBucket(c.bucket_id);
7641 bucket->SetFromString(str);
7642 return error::kNoError;
7645 error::Error GLES2DecoderImpl::HandleBufferData(
7646 uint32 immediate_data_size, const cmds::BufferData& c) {
7647 GLenum target = static_cast<GLenum>(c.target);
7648 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7649 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7650 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7651 GLenum usage = static_cast<GLenum>(c.usage);
7652 const void* data = NULL;
7653 if (data_shm_id != 0 || data_shm_offset != 0) {
7654 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7656 return error::kOutOfBounds;
7659 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7660 return error::kNoError;
7663 void GLES2DecoderImpl::DoBufferSubData(
7664 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7665 // Just delegate it. Some validation is actually done before this.
7666 buffer_manager()->ValidateAndDoBufferSubData(
7667 &state_, target, offset, size, data);
7670 bool GLES2DecoderImpl::ClearLevel(
7671 unsigned service_id,
7672 unsigned bind_target,
7679 bool is_texture_immutable) {
7680 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7681 if (feature_info_->feature_flags().angle_depth_texture &&
7682 (channels & GLES2Util::kDepth) != 0) {
7683 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7684 // on depth formats.
7686 glGenFramebuffersEXT(1, &fb);
7687 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7689 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7690 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7691 GL_DEPTH_ATTACHMENT;
7693 glFramebufferTexture2DEXT(
7694 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7695 // ANGLE promises a depth only attachment ok.
7696 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7697 GL_FRAMEBUFFER_COMPLETE) {
7704 glDisable(GL_SCISSOR_TEST);
7705 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7707 RestoreClearState();
7709 glDeleteFramebuffersEXT(1, &fb);
7710 Framebuffer* framebuffer =
7711 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7712 GLuint fb_service_id =
7713 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7714 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7718 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7721 uint32 padded_row_size;
7722 if (!GLES2Util::ComputeImageDataSizes(
7723 width, height, format, type, state_.unpack_alignment, &size,
7724 NULL, &padded_row_size)) {
7728 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7732 if (size > kMaxZeroSize) {
7733 if (kMaxZeroSize < padded_row_size) {
7734 // That'd be an awfully large texture.
7737 // We should never have a large total size with a zero row size.
7738 DCHECK_GT(padded_row_size, 0U);
7739 tile_height = kMaxZeroSize / padded_row_size;
7740 if (!GLES2Util::ComputeImageDataSizes(
7741 width, tile_height, format, type, state_.unpack_alignment, &size,
7746 tile_height = height;
7749 // Assumes the size has already been checked.
7750 scoped_ptr<char[]> zero(new char[size]);
7751 memset(zero.get(), 0, size);
7752 glBindTexture(bind_target, service_id);
7755 while (y < height) {
7756 GLint h = y + tile_height > height ? height - y : tile_height;
7757 if (is_texture_immutable || h != height) {
7758 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7761 target, level, format, width, h, 0, format, type, zero.get());
7765 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7766 &state_, bind_target);
7767 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7773 const int kS3TCBlockWidth = 4;
7774 const int kS3TCBlockHeight = 4;
7775 const int kS3TCDXT1BlockSize = 8;
7776 const int kS3TCDXT3AndDXT5BlockSize = 16;
7777 const int kETC1BlockWidth = 4;
7778 const int kETC1BlockHeight = 4;
7779 const int kETC1BlockSize = 8;
7781 bool IsValidDXTSize(GLint level, GLsizei size) {
7782 return (size == 1) ||
7783 (size == 2) || !(size % kS3TCBlockWidth);
7786 } // anonymous namespace.
7788 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7789 const char* function_name,
7790 GLsizei width, GLsizei height, GLenum format, size_t size) {
7791 unsigned int bytes_required = 0;
7794 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7795 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7796 int num_blocks_across =
7797 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7798 int num_blocks_down =
7799 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7800 int num_blocks = num_blocks_across * num_blocks_down;
7801 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7804 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7805 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7806 int num_blocks_across =
7807 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7808 int num_blocks_down =
7809 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7810 int num_blocks = num_blocks_across * num_blocks_down;
7811 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7814 case GL_ETC1_RGB8_OES: {
7815 int num_blocks_across =
7816 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7817 int num_blocks_down =
7818 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7819 int num_blocks = num_blocks_across * num_blocks_down;
7820 bytes_required = num_blocks * kETC1BlockSize;
7824 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7828 if (size != bytes_required) {
7830 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7837 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7838 const char* function_name,
7839 GLint level, GLsizei width, GLsizei height, GLenum format) {
7841 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7842 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7843 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7844 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7845 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7847 GL_INVALID_OPERATION, function_name,
7848 "width or height invalid for level");
7853 case GL_ETC1_RGB8_OES:
7854 if (width <= 0 || height <= 0) {
7856 GL_INVALID_OPERATION, function_name,
7857 "width or height invalid for level");
7866 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7867 const char* function_name,
7868 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7869 GLsizei width, GLsizei height, GLenum format,
7871 if (xoffset < 0 || yoffset < 0) {
7873 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7878 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7879 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7880 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7881 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7882 const int kBlockWidth = 4;
7883 const int kBlockHeight = 4;
7884 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7886 GL_INVALID_OPERATION, function_name,
7887 "xoffset or yoffset not multiple of 4");
7890 GLsizei tex_width = 0;
7891 GLsizei tex_height = 0;
7892 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7893 width - xoffset > tex_width ||
7894 height - yoffset > tex_height) {
7896 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7899 return ValidateCompressedTexDimensions(
7900 function_name, level, width, height, format);
7902 case GL_ETC1_RGB8_OES: {
7904 GL_INVALID_OPERATION, function_name,
7905 "not supported for ECT1_RGB8_OES textures");
7913 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7916 GLenum internal_format,
7922 // TODO(gman): Validate image_size is correct for width, height and format.
7923 if (!validators_->texture_target.IsValid(target)) {
7924 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7925 "glCompressedTexImage2D", target, "target");
7926 return error::kNoError;
7928 if (!validators_->compressed_texture_format.IsValid(
7930 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7931 "glCompressedTexImage2D", internal_format, "internal_format");
7932 return error::kNoError;
7934 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7938 "glCompressedTexImage2D", "dimensions out of range");
7939 return error::kNoError;
7941 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7946 "glCompressedTexImage2D", "unknown texture target");
7947 return error::kNoError;
7949 Texture* texture = texture_ref->texture();
7950 if (texture->IsImmutable()) {
7952 GL_INVALID_OPERATION,
7953 "glCompressedTexImage2D", "texture is immutable");
7954 return error::kNoError;
7957 if (!ValidateCompressedTexDimensions(
7958 "glCompressedTexImage2D", level, width, height, internal_format) ||
7959 !ValidateCompressedTexFuncData(
7960 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
7961 return error::kNoError;
7964 if (!EnsureGPUMemoryAvailable(image_size)) {
7966 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
7967 return error::kNoError;
7970 if (texture->IsAttachedToFramebuffer()) {
7971 framebuffer_state_.clear_state_dirty = true;
7974 scoped_ptr<int8[]> zero;
7976 zero.reset(new int8[image_size]);
7977 memset(zero.get(), 0, image_size);
7980 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
7981 glCompressedTexImage2D(
7982 target, level, internal_format, width, height, border, image_size, data);
7983 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
7984 if (error == GL_NO_ERROR) {
7985 texture_manager()->SetLevelInfo(
7986 texture_ref, target, level, internal_format,
7987 width, height, 1, border, 0, 0, true);
7989 return error::kNoError;
7992 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
7993 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
7994 GLenum target = static_cast<GLenum>(c.target);
7995 GLint level = static_cast<GLint>(c.level);
7996 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7997 GLsizei width = static_cast<GLsizei>(c.width);
7998 GLsizei height = static_cast<GLsizei>(c.height);
7999 GLint border = static_cast<GLint>(c.border);
8000 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8001 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8002 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8003 const void* data = NULL;
8004 if (data_shm_id != 0 || data_shm_offset != 0) {
8005 data = GetSharedMemoryAs<const void*>(
8006 data_shm_id, data_shm_offset, image_size);
8008 return error::kOutOfBounds;
8011 return DoCompressedTexImage2D(
8012 target, level, internal_format, width, height, border, image_size, data);
8015 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8016 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
8017 GLenum target = static_cast<GLenum>(c.target);
8018 GLint level = static_cast<GLint>(c.level);
8019 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8020 GLsizei width = static_cast<GLsizei>(c.width);
8021 GLsizei height = static_cast<GLsizei>(c.height);
8022 GLint border = static_cast<GLint>(c.border);
8023 Bucket* bucket = GetBucket(c.bucket_id);
8025 return error::kInvalidArguments;
8027 uint32 data_size = bucket->size();
8028 GLsizei imageSize = data_size;
8029 const void* data = bucket->GetData(0, data_size);
8031 return error::kInvalidArguments;
8033 return DoCompressedTexImage2D(
8034 target, level, internal_format, width, height, border,
8038 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8039 uint32 immediate_data_size,
8040 const cmds::CompressedTexSubImage2DBucket& c) {
8041 GLenum target = static_cast<GLenum>(c.target);
8042 GLint level = static_cast<GLint>(c.level);
8043 GLint xoffset = static_cast<GLint>(c.xoffset);
8044 GLint yoffset = static_cast<GLint>(c.yoffset);
8045 GLsizei width = static_cast<GLsizei>(c.width);
8046 GLsizei height = static_cast<GLsizei>(c.height);
8047 GLenum format = static_cast<GLenum>(c.format);
8048 Bucket* bucket = GetBucket(c.bucket_id);
8050 return error::kInvalidArguments;
8052 uint32 data_size = bucket->size();
8053 GLsizei imageSize = data_size;
8054 const void* data = bucket->GetData(0, data_size);
8056 return error::kInvalidArguments;
8058 if (!validators_->texture_target.IsValid(target)) {
8060 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8061 return error::kNoError;
8063 if (!validators_->compressed_texture_format.IsValid(format)) {
8064 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8065 "glCompressedTexSubImage2D", format, "format");
8066 return error::kNoError;
8070 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8071 return error::kNoError;
8075 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8076 return error::kNoError;
8078 if (imageSize < 0) {
8080 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8081 return error::kNoError;
8083 DoCompressedTexSubImage2D(
8084 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8085 return error::kNoError;
8088 error::Error GLES2DecoderImpl::HandleTexImage2D(
8089 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8090 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
8091 // Set as failed for now, but if it successed, this will be set to not failed.
8092 texture_state_.tex_image_2d_failed = true;
8093 GLenum target = static_cast<GLenum>(c.target);
8094 GLint level = static_cast<GLint>(c.level);
8095 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8096 // for internalformat.
8097 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8098 GLsizei width = static_cast<GLsizei>(c.width);
8099 GLsizei height = static_cast<GLsizei>(c.height);
8100 GLint border = static_cast<GLint>(c.border);
8101 GLenum format = static_cast<GLenum>(c.format);
8102 GLenum type = static_cast<GLenum>(c.type);
8103 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8104 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8106 if (!GLES2Util::ComputeImageDataSizes(
8107 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8109 return error::kOutOfBounds;
8111 const void* pixels = NULL;
8112 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8113 pixels = GetSharedMemoryAs<const void*>(
8114 pixels_shm_id, pixels_shm_offset, pixels_size);
8116 return error::kOutOfBounds;
8120 TextureManager::DoTextImage2DArguments args = {
8121 target, level, internal_format, width, height, border, format, type,
8122 pixels, pixels_size};
8123 texture_manager()->ValidateAndDoTexImage2D(
8124 &texture_state_, &state_, &framebuffer_state_, args);
8125 return error::kNoError;
8128 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8137 const void * data) {
8138 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8142 GL_INVALID_OPERATION,
8143 "glCompressedTexSubImage2D", "unknown texture for target");
8146 Texture* texture = texture_ref->texture();
8148 GLenum internal_format = 0;
8149 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8151 GL_INVALID_OPERATION,
8152 "glCompressedTexSubImage2D", "level does not exist.");
8155 if (internal_format != format) {
8157 GL_INVALID_OPERATION,
8158 "glCompressedTexSubImage2D", "format does not match internal format.");
8161 if (!texture->ValidForTexture(
8162 target, level, xoffset, yoffset, width, height, type)) {
8164 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8168 if (!ValidateCompressedTexFuncData(
8169 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8170 !ValidateCompressedTexSubDimensions(
8171 "glCompressedTexSubImage2D",
8172 target, level, xoffset, yoffset, width, height, format, texture)) {
8177 // Note: There is no need to deal with texture cleared tracking here
8178 // because the validation above means you can only get here if the level
8179 // is already a matching compressed format and in that case
8180 // CompressedTexImage2D already cleared the texture.
8181 glCompressedTexSubImage2D(
8182 target, level, xoffset, yoffset, width, height, format, image_size, data);
8186 GLint start, GLint range, GLint sourceRange,
8187 GLint* out_start, GLint* out_range) {
8194 GLint end = start + range;
8195 if (end > sourceRange) {
8196 range -= end - sourceRange;
8202 void GLES2DecoderImpl::DoCopyTexImage2D(
8205 GLenum internal_format,
8211 DCHECK(!ShouldDeferReads());
8212 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8216 GL_INVALID_OPERATION,
8217 "glCopyTexImage2D", "unknown texture for target");
8220 Texture* texture = texture_ref->texture();
8221 if (texture->IsImmutable()) {
8223 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8225 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8228 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8231 if (!texture_manager()->ValidateFormatAndTypeCombination(
8232 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8233 GL_UNSIGNED_BYTE)) {
8237 // Check we have compatible formats.
8238 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8239 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8240 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8242 if ((channels_needed & channels_exist) != channels_needed) {
8244 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8248 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8250 GL_INVALID_OPERATION,
8251 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8255 uint32 estimated_size = 0;
8256 if (!GLES2Util::ComputeImageDataSizes(
8257 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8258 &estimated_size, NULL, NULL)) {
8260 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8264 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8265 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8269 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8273 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8274 ScopedResolvedFrameBufferBinder binder(this, false, true);
8275 gfx::Size size = GetBoundReadFrameBufferSize();
8277 if (texture->IsAttachedToFramebuffer()) {
8278 framebuffer_state_.clear_state_dirty = true;
8281 // Clip to size to source dimensions
8284 GLint copyWidth = 0;
8285 GLint copyHeight = 0;
8286 Clip(x, width, size.width(), ©X, ©Width);
8287 Clip(y, height, size.height(), ©Y, ©Height);
8291 copyWidth != width ||
8292 copyHeight != height) {
8293 // some part was clipped so clear the texture.
8295 texture->service_id(), texture->target(),
8296 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
8297 texture->IsImmutable())) {
8299 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8302 if (copyHeight > 0 && copyWidth > 0) {
8303 GLint dx = copyX - x;
8304 GLint dy = copyY - y;
8307 glCopyTexSubImage2D(target, level,
8308 destX, destY, copyX, copyY,
8309 copyWidth, copyHeight);
8312 glCopyTexImage2D(target, level, internal_format,
8313 copyX, copyY, copyWidth, copyHeight, border);
8315 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8316 if (error == GL_NO_ERROR) {
8317 texture_manager()->SetLevelInfo(
8318 texture_ref, target, level, internal_format, width, height, 1,
8319 border, internal_format, GL_UNSIGNED_BYTE, true);
8323 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8332 DCHECK(!ShouldDeferReads());
8333 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8337 GL_INVALID_OPERATION,
8338 "glCopyTexSubImage2D", "unknown texture for target");
8341 Texture* texture = texture_ref->texture();
8344 if (!texture->GetLevelType(target, level, &type, &format) ||
8345 !texture->ValidForTexture(
8346 target, level, xoffset, yoffset, width, height, type)) {
8348 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8351 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8353 GL_INVALID_OPERATION,
8354 "glCopyTexSubImage2D", "async upload pending for texture");
8358 // Check we have compatible formats.
8359 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8360 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8361 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8363 if (!channels_needed ||
8364 (channels_needed & channels_exist) != channels_needed) {
8366 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8370 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8372 GL_INVALID_OPERATION,
8373 "glCopySubImage2D", "can not be used with depth or stencil textures");
8377 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8381 ScopedResolvedFrameBufferBinder binder(this, false, true);
8382 gfx::Size size = GetBoundReadFrameBufferSize();
8385 GLint copyWidth = 0;
8386 GLint copyHeight = 0;
8387 Clip(x, width, size.width(), ©X, ©Width);
8388 Clip(y, height, size.height(), ©Y, ©Height);
8390 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8392 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8398 copyWidth != width ||
8399 copyHeight != height) {
8400 // some part was clipped so clear the sub rect.
8401 uint32 pixels_size = 0;
8402 if (!GLES2Util::ComputeImageDataSizes(
8403 width, height, format, type, state_.unpack_alignment, &pixels_size,
8406 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8409 scoped_ptr<char[]> zero(new char[pixels_size]);
8410 memset(zero.get(), 0, pixels_size);
8412 target, level, xoffset, yoffset, width, height,
8413 format, type, zero.get());
8416 if (copyHeight > 0 && copyWidth > 0) {
8417 GLint dx = copyX - x;
8418 GLint dy = copyY - y;
8419 GLint destX = xoffset + dx;
8420 GLint destY = yoffset + dy;
8421 glCopyTexSubImage2D(target, level,
8422 destX, destY, copyX, copyY,
8423 copyWidth, copyHeight);
8427 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8428 error::Error* error,
8429 const char* function_name,
8438 const void * data) {
8439 (*error) = error::kNoError;
8440 if (!validators_->texture_target.IsValid(target)) {
8441 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8445 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8449 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8452 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8456 GL_INVALID_OPERATION,
8457 function_name, "unknown texture for target");
8460 Texture* texture = texture_ref->texture();
8461 GLenum current_type = 0;
8462 GLenum internal_format = 0;
8463 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
8465 GL_INVALID_OPERATION, function_name, "level does not exist.");
8468 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8469 function_name, format, type, internal_format, level)) {
8472 if (type != current_type) {
8474 GL_INVALID_OPERATION,
8475 function_name, "type does not match type of texture.");
8478 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8480 GL_INVALID_OPERATION,
8481 function_name, "async upload pending for texture");
8484 if (!texture->ValidForTexture(
8485 target, level, xoffset, yoffset, width, height, type)) {
8486 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8489 if ((GLES2Util::GetChannelsForFormat(format) &
8490 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8492 GL_INVALID_OPERATION,
8493 function_name, "can not supply data for depth or stencil textures");
8497 (*error) = error::kOutOfBounds;
8503 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8512 const void * data) {
8513 error::Error error = error::kNoError;
8514 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8515 xoffset, yoffset, width, height, format, type, data)) {
8518 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8520 Texture* texture = texture_ref->texture();
8521 GLsizei tex_width = 0;
8522 GLsizei tex_height = 0;
8523 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8525 if (xoffset != 0 || yoffset != 0 ||
8526 width != tex_width || height != tex_height) {
8527 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8530 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8531 return error::kNoError;
8533 ScopedTextureUploadTimer timer(&texture_state_);
8535 target, level, xoffset, yoffset, width, height, format, type, data);
8536 return error::kNoError;
8539 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8540 !texture->IsImmutable()) {
8541 ScopedTextureUploadTimer timer(&texture_state_);
8542 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8543 // same as internal_foramt. If that changes we'll need to look them up.
8545 target, level, format, width, height, 0, format, type, data);
8547 ScopedTextureUploadTimer timer(&texture_state_);
8549 target, level, xoffset, yoffset, width, height, format, type, data);
8551 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8552 return error::kNoError;
8555 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8556 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8557 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8558 GLboolean internal = static_cast<GLboolean>(c.internal);
8559 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8560 return error::kNoError;
8562 GLenum target = static_cast<GLenum>(c.target);
8563 GLint level = static_cast<GLint>(c.level);
8564 GLint xoffset = static_cast<GLint>(c.xoffset);
8565 GLint yoffset = static_cast<GLint>(c.yoffset);
8566 GLsizei width = static_cast<GLsizei>(c.width);
8567 GLsizei height = static_cast<GLsizei>(c.height);
8568 GLenum format = static_cast<GLenum>(c.format);
8569 GLenum type = static_cast<GLenum>(c.type);
8571 if (!GLES2Util::ComputeImageDataSizes(
8572 width, height, format, type, state_.unpack_alignment, &data_size,
8574 return error::kOutOfBounds;
8576 const void* pixels = GetSharedMemoryAs<const void*>(
8577 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8578 return DoTexSubImage2D(
8579 target, level, xoffset, yoffset, width, height, format, type, pixels);
8582 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8583 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8584 GLuint index = static_cast<GLuint>(c.index);
8585 GLenum pname = static_cast<GLenum>(c.pname);
8586 typedef cmds::GetVertexAttribPointerv::Result Result;
8587 Result* result = GetSharedMemoryAs<Result*>(
8588 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8590 return error::kOutOfBounds;
8592 // Check that the client initialized the result.
8593 if (result->size != 0) {
8594 return error::kInvalidArguments;
8596 if (!validators_->vertex_pointer.IsValid(pname)) {
8597 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8598 "glGetVertexAttribPointerv", pname, "pname");
8599 return error::kNoError;
8601 if (index >= group_->max_vertex_attribs()) {
8603 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8604 return error::kNoError;
8606 result->SetNumResults(1);
8607 *result->GetData() =
8608 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8609 return error::kNoError;
8612 bool GLES2DecoderImpl::GetUniformSetup(
8613 GLuint program_id, GLint fake_location,
8614 uint32 shm_id, uint32 shm_offset,
8615 error::Error* error, GLint* real_location,
8616 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8619 DCHECK(result_pointer);
8620 DCHECK(result_type);
8621 DCHECK(real_location);
8622 *error = error::kNoError;
8623 // Make sure we have enough room for the result on failure.
8624 SizedResult<GLint>* result;
8625 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8626 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8628 *error = error::kOutOfBounds;
8631 *result_pointer = result;
8632 // Set the result size to 0 so the client does not have to check for success.
8633 result->SetNumResults(0);
8634 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8638 if (!program->IsValid()) {
8639 // Program was not linked successfully. (ie, glLinkProgram)
8641 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8644 *service_id = program->service_id();
8645 GLint array_index = -1;
8646 const Program::UniformInfo* uniform_info =
8647 program->GetUniformInfoByFakeLocation(
8648 fake_location, real_location, &array_index);
8649 if (!uniform_info) {
8650 // No such location.
8652 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8655 GLenum type = uniform_info->type;
8656 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8658 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8661 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8662 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8664 *error = error::kOutOfBounds;
8667 result->size = size;
8668 *result_type = type;
8672 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8673 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8674 GLuint program = c.program;
8675 GLint fake_location = c.location;
8678 GLint real_location = -1;
8681 if (GetUniformSetup(
8682 program, fake_location, c.params_shm_id, c.params_shm_offset,
8683 &error, &real_location, &service_id, &result, &result_type)) {
8685 service_id, real_location,
8686 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8691 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8692 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8693 GLuint program = c.program;
8694 GLint fake_location = c.location;
8696 GLint real_location = -1;
8698 typedef cmds::GetUniformfv::Result Result;
8701 if (GetUniformSetup(
8702 program, fake_location, c.params_shm_id, c.params_shm_offset,
8703 &error, &real_location, &service_id,
8704 reinterpret_cast<void**>(&result), &result_type)) {
8705 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8706 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8707 GLsizei num_values = result->GetNumResults();
8708 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8709 glGetUniformiv(service_id, real_location, temp.get());
8710 GLfloat* dst = result->GetData();
8711 for (GLsizei ii = 0; ii < num_values; ++ii) {
8712 dst[ii] = (temp[ii] != 0);
8715 glGetUniformfv(service_id, real_location, result->GetData());
8721 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8722 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8723 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8724 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8725 typedef cmds::GetShaderPrecisionFormat::Result Result;
8726 Result* result = GetSharedMemoryAs<Result*>(
8727 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8729 return error::kOutOfBounds;
8731 // Check that the client initialized the result.
8732 if (result->success != 0) {
8733 return error::kInvalidArguments;
8735 if (!validators_->shader_type.IsValid(shader_type)) {
8736 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8737 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8738 return error::kNoError;
8740 if (!validators_->shader_precision.IsValid(precision_type)) {
8741 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8742 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8743 return error::kNoError;
8746 result->success = 1; // true
8748 GLint range[2] = { 0, 0 };
8749 GLint precision = 0;
8750 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8752 result->min_range = range[0];
8753 result->max_range = range[1];
8754 result->precision = precision;
8756 return error::kNoError;
8759 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8760 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8761 uint32 result_size = c.result_size;
8762 GLuint program_id = static_cast<GLuint>(c.program);
8763 Program* program = GetProgramInfoNotShader(
8764 program_id, "glGetAttachedShaders");
8766 return error::kNoError;
8768 typedef cmds::GetAttachedShaders::Result Result;
8769 uint32 max_count = Result::ComputeMaxResults(result_size);
8770 Result* result = GetSharedMemoryAs<Result*>(
8771 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8773 return error::kOutOfBounds;
8775 // Check that the client initialized the result.
8776 if (result->size != 0) {
8777 return error::kInvalidArguments;
8780 glGetAttachedShaders(
8781 program->service_id(), max_count, &count, result->GetData());
8782 for (GLsizei ii = 0; ii < count; ++ii) {
8783 if (!shader_manager()->GetClientId(result->GetData()[ii],
8784 &result->GetData()[ii])) {
8786 return error::kGenericError;
8789 result->SetNumResults(count);
8790 return error::kNoError;
8793 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8794 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8795 GLuint program_id = c.program;
8796 GLuint index = c.index;
8797 uint32 name_bucket_id = c.name_bucket_id;
8798 typedef cmds::GetActiveUniform::Result Result;
8799 Result* result = GetSharedMemoryAs<Result*>(
8800 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8802 return error::kOutOfBounds;
8804 // Check that the client initialized the result.
8805 if (result->success != 0) {
8806 return error::kInvalidArguments;
8808 Program* program = GetProgramInfoNotShader(
8809 program_id, "glGetActiveUniform");
8811 return error::kNoError;
8813 const Program::UniformInfo* uniform_info =
8814 program->GetUniformInfo(index);
8815 if (!uniform_info) {
8817 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8818 return error::kNoError;
8820 result->success = 1; // true.
8821 result->size = uniform_info->size;
8822 result->type = uniform_info->type;
8823 Bucket* bucket = CreateBucket(name_bucket_id);
8824 bucket->SetFromString(uniform_info->name.c_str());
8825 return error::kNoError;
8828 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
8829 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8830 GLuint program_id = c.program;
8831 GLuint index = c.index;
8832 uint32 name_bucket_id = c.name_bucket_id;
8833 typedef cmds::GetActiveAttrib::Result Result;
8834 Result* result = GetSharedMemoryAs<Result*>(
8835 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8837 return error::kOutOfBounds;
8839 // Check that the client initialized the result.
8840 if (result->success != 0) {
8841 return error::kInvalidArguments;
8843 Program* program = GetProgramInfoNotShader(
8844 program_id, "glGetActiveAttrib");
8846 return error::kNoError;
8848 const Program::VertexAttrib* attrib_info =
8849 program->GetAttribInfo(index);
8852 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
8853 return error::kNoError;
8855 result->success = 1; // true.
8856 result->size = attrib_info->size;
8857 result->type = attrib_info->type;
8858 Bucket* bucket = CreateBucket(name_bucket_id);
8859 bucket->SetFromString(attrib_info->name.c_str());
8860 return error::kNoError;
8863 error::Error GLES2DecoderImpl::HandleShaderBinary(
8864 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
8865 #if 1 // No binary shader support.
8866 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
8867 return error::kNoError;
8869 GLsizei n = static_cast<GLsizei>(c.n);
8871 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
8872 return error::kNoError;
8874 GLsizei length = static_cast<GLsizei>(c.length);
8876 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
8877 return error::kNoError;
8880 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8881 return error::kOutOfBounds;
8883 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8884 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8885 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8886 const void* binary = GetSharedMemoryAs<const void*>(
8887 c.binary_shm_id, c.binary_shm_offset, length);
8888 if (shaders == NULL || binary == NULL) {
8889 return error::kOutOfBounds;
8891 scoped_array<GLuint> service_ids(new GLuint[n]);
8892 for (GLsizei ii = 0; ii < n; ++ii) {
8893 Shader* shader = GetShader(shaders[ii]);
8895 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
8896 return error::kNoError;
8898 service_ids[ii] = shader->service_id();
8900 // TODO(gman): call glShaderBinary
8901 return error::kNoError;
8905 void GLES2DecoderImpl::DoSwapBuffers() {
8906 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8908 int this_frame_number = frame_number_++;
8909 // TRACE_EVENT for gpu tests:
8910 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
8911 TRACE_EVENT_SCOPE_THREAD,
8912 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8913 "width", (is_offscreen ? offscreen_size_.width() :
8914 surface_->GetSize().width()));
8915 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
8916 "offscreen", is_offscreen,
8917 "frame", this_frame_number);
8919 TRACE_EVENT_SYNTHETIC_DELAY("gpu.SwapBuffers");
8923 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8926 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8927 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8928 is_offscreen ? offscreen_size_ : surface_->GetSize());
8931 // If offscreen then don't actually SwapBuffers to the display. Just copy
8932 // the rendered frame to another frame buffer.
8934 TRACE_EVENT2("gpu", "Offscreen",
8935 "width", offscreen_size_.width(), "height", offscreen_size_.height());
8936 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8937 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8938 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8940 if (workarounds().needs_offscreen_buffer_workaround) {
8941 offscreen_saved_frame_buffer_->Create();
8945 // Allocate the offscreen saved color texture.
8946 DCHECK(offscreen_saved_color_format_);
8947 offscreen_saved_color_texture_->AllocateStorage(
8948 offscreen_size_, offscreen_saved_color_format_, false);
8950 offscreen_saved_frame_buffer_->AttachRenderTexture(
8951 offscreen_saved_color_texture_.get());
8952 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8953 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8954 GL_FRAMEBUFFER_COMPLETE) {
8955 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8956 << "because offscreen saved FBO was incomplete.";
8957 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8961 // Clear the offscreen color texture.
8962 // TODO(piman): Is this still necessary?
8964 ScopedFrameBufferBinder binder(this,
8965 offscreen_saved_frame_buffer_->id());
8966 glClearColor(0, 0, 0, 0);
8967 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8968 glDisable(GL_SCISSOR_TEST);
8969 glClear(GL_COLOR_BUFFER_BIT);
8970 RestoreClearState();
8974 UpdateParentTextureInfo();
8977 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
8979 ScopedGLErrorSuppressor suppressor(
8980 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
8982 if (IsOffscreenBufferMultisampled()) {
8983 // For multisampled buffers, resolve the frame buffer.
8984 ScopedResolvedFrameBufferBinder binder(this, true, false);
8986 ScopedFrameBufferBinder binder(this,
8987 offscreen_target_frame_buffer_->id());
8989 if (offscreen_target_buffer_preserved_) {
8990 // Copy the target frame buffer to the saved offscreen texture.
8991 offscreen_saved_color_texture_->Copy(
8992 offscreen_saved_color_texture_->size(),
8993 offscreen_saved_color_format_);
8995 // Flip the textures in the parent context via the texture manager.
8996 if (!!offscreen_saved_color_texture_info_.get())
8997 offscreen_saved_color_texture_info_->texture()->
8998 SetServiceId(offscreen_target_color_texture_->id());
9000 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9001 offscreen_target_frame_buffer_->AttachRenderTexture(
9002 offscreen_target_color_texture_.get());
9005 // Ensure the side effects of the copy are visible to the parent
9006 // context. There is no need to do this for ANGLE because it uses a
9007 // single D3D device for all contexts.
9008 if (!feature_info_->feature_flags().is_angle)
9012 if (!surface_->SwapBuffers()) {
9013 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9014 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9019 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9020 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
9021 Bucket* bucket = GetBucket(c.bucket_id);
9022 if (!bucket || bucket->size() == 0) {
9023 return error::kInvalidArguments;
9025 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9026 Result* result = GetSharedMemoryAs<Result*>(
9027 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9029 return error::kOutOfBounds;
9031 // Check that the client initialized the result.
9033 return error::kInvalidArguments;
9035 std::string feature_str;
9036 if (!bucket->GetAsString(&feature_str)) {
9037 return error::kInvalidArguments;
9040 // TODO(gman): make this some kind of table to function pointer thingy.
9041 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9042 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9043 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9044 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9045 // TODO(gman): decide how to remove the need for this const_cast.
9046 // I could make validators_ non const but that seems bad as this is the only
9047 // place it is needed. I could make some special friend class of validators
9048 // just to allow this to set them. That seems silly. I could refactor this
9049 // code to use the extension mechanism or the initialization attributes to
9050 // turn this feature on. Given that the only real point of this is to make
9051 // the conformance tests pass and given that there is lots of real work that
9052 // needs to be done it seems like refactoring for one to one of those
9053 // methods is a very low priority.
9054 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9055 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9056 force_webgl_glsl_validation_ = true;
9057 InitializeShaderTranslator();
9059 return error::kNoError;
9062 *result = 1; // true.
9063 return error::kNoError;
9066 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9067 uint32 immediate_data_size,
9068 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9069 Bucket* bucket = CreateBucket(c.bucket_id);
9070 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9071 info->Initialize(disallowed_features_);
9072 bucket->SetFromString(info->extensions().c_str());
9073 return error::kNoError;
9076 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9077 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9078 Bucket* bucket = GetBucket(c.bucket_id);
9079 if (!bucket || bucket->size() == 0) {
9080 return error::kInvalidArguments;
9082 std::string feature_str;
9083 if (!bucket->GetAsString(&feature_str)) {
9084 return error::kInvalidArguments;
9087 bool desire_webgl_glsl_validation =
9088 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9089 bool desire_standard_derivatives = false;
9090 bool desire_frag_depth = false;
9091 bool desire_draw_buffers = false;
9092 if (force_webgl_glsl_validation_) {
9093 desire_standard_derivatives =
9094 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9096 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9097 desire_draw_buffers =
9098 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9101 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9102 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9103 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9104 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9105 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9106 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9107 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9108 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9109 InitializeShaderTranslator();
9112 UpdateCapabilities();
9114 return error::kNoError;
9117 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9118 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9119 GLuint count = c.count;
9121 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9122 return error::kOutOfBounds;
9124 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9125 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9126 if (pnames == NULL) {
9127 return error::kOutOfBounds;
9130 // We have to copy them since we use them twice so the client
9131 // can't change them between the time we validate them and the time we use
9133 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9134 memcpy(enums.get(), pnames, pnames_size);
9136 // Count up the space needed for the result.
9137 uint32 num_results = 0;
9138 for (GLuint ii = 0; ii < count; ++ii) {
9139 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9141 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9142 "glGetMultipleCHROMIUM", enums[ii], "pname");
9143 return error::kNoError;
9145 // Num will never be more than 4.
9147 if (!SafeAddUint32(num_results, num, &num_results)) {
9148 return error::kOutOfBounds;
9152 uint32 result_size = 0;
9153 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9154 return error::kOutOfBounds;
9157 if (result_size != static_cast<uint32>(c.size)) {
9160 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9161 return error::kNoError;
9164 GLint* results = GetSharedMemoryAs<GLint*>(
9165 c.results_shm_id, c.results_shm_offset, result_size);
9166 if (results == NULL) {
9167 return error::kOutOfBounds;
9170 // Check the results have been cleared in case the context was lost.
9171 for (uint32 ii = 0; ii < num_results; ++ii) {
9173 return error::kInvalidArguments;
9178 GLint* start = results;
9179 for (GLuint ii = 0; ii < count; ++ii) {
9180 GLsizei num_written = 0;
9181 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9182 !GetHelper(enums[ii], results, &num_written)) {
9183 DoGetIntegerv(enums[ii], results);
9185 results += num_written;
9188 // Just to verify. Should this be a DCHECK?
9189 if (static_cast<uint32>(results - start) != num_results) {
9190 return error::kOutOfBounds;
9193 return error::kNoError;
9196 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9197 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9198 GLuint program_id = static_cast<GLuint>(c.program);
9199 uint32 bucket_id = c.bucket_id;
9200 Bucket* bucket = CreateBucket(bucket_id);
9201 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9202 Program* program = NULL;
9203 program = GetProgram(program_id);
9204 if (!program || !program->IsValid()) {
9205 return error::kNoError;
9207 program->GetProgramInfo(program_manager(), bucket);
9208 return error::kNoError;
9211 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9212 switch (reset_status_) {
9214 // TODO(kbr): improve the precision of the error code in this case.
9215 // Consider delegating to context for error code if MakeCurrent fails.
9216 return error::kUnknown;
9217 case GL_GUILTY_CONTEXT_RESET_ARB:
9218 return error::kGuilty;
9219 case GL_INNOCENT_CONTEXT_RESET_ARB:
9220 return error::kInnocent;
9221 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9222 return error::kUnknown;
9226 return error::kUnknown;
9229 bool GLES2DecoderImpl::WasContextLost() {
9230 if (reset_status_ != GL_NO_ERROR) {
9233 if (context_->WasAllocatedUsingRobustnessExtension()) {
9234 GLenum status = GL_NO_ERROR;
9235 if (has_robustness_extension_)
9236 status = glGetGraphicsResetStatusARB();
9237 if (status != GL_NO_ERROR) {
9238 // The graphics card was reset. Signal a lost context to the application.
9239 reset_status_ = status;
9240 reset_by_robustness_extension_ = true;
9241 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9242 << " context lost via ARB/EXT_robustness. Reset status = "
9243 << GLES2Util::GetStringEnum(status);
9250 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9251 return WasContextLost() && reset_by_robustness_extension_;
9254 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9255 // Only loses the context once.
9256 if (reset_status_ != GL_NO_ERROR) {
9260 // Marks this context as lost.
9261 reset_status_ = reset_status;
9262 current_decoder_error_ = error::kLostContext;
9265 error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9266 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
9267 GLenum current = static_cast<GLenum>(c.current);
9268 GLenum other = static_cast<GLenum>(c.other);
9269 if (!validators_->reset_status.IsValid(current)) {
9270 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9271 "glLoseContextCHROMIUM", current, "current");
9273 if (!validators_->reset_status.IsValid(other)) {
9274 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
9276 group_->LoseContexts(other);
9277 reset_status_ = current;
9278 current_decoder_error_ = error::kLostContext;
9279 return error::kLostContext;
9282 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9283 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9284 return error::kUnknownCommand;
9287 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9288 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9289 if (wait_sync_point_callback_.is_null())
9290 return error::kNoError;
9292 return wait_sync_point_callback_.Run(c.sync_point) ?
9293 error::kNoError : error::kDeferCommandUntilLater;
9296 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9297 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9298 if (surface_->DeferDraws())
9299 return error::kDeferCommandUntilLater;
9300 if (!surface_->SetBackbufferAllocation(false))
9301 return error::kLostContext;
9302 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9303 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9304 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9305 return error::kNoError;
9308 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9309 GLsizei n, const GLuint* client_ids) {
9310 for (GLsizei ii = 0; ii < n; ++ii) {
9311 if (query_manager_->GetQuery(client_ids[ii])) {
9315 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
9319 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9320 GLsizei n, const GLuint* client_ids) {
9321 for (GLsizei ii = 0; ii < n; ++ii) {
9322 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9323 if (query && !query->IsDeleted()) {
9324 ContextState::QueryMap::iterator it =
9325 state_.current_queries.find(query->target());
9326 if (it != state_.current_queries.end())
9327 state_.current_queries.erase(it);
9329 query->Destroy(true);
9330 query_manager_->RemoveQuery(client_ids[ii]);
9335 bool GLES2DecoderImpl::ProcessPendingQueries() {
9336 if (query_manager_.get() == NULL) {
9339 if (!query_manager_->ProcessPendingQueries()) {
9340 current_decoder_error_ = error::kOutOfBounds;
9342 return query_manager_->HavePendingQueries();
9345 // Note that if there are no pending readpixels right now,
9346 // this function will call the callback immediately.
9347 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9348 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9349 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9355 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9356 while (!pending_readpixel_fences_.empty() &&
9357 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9358 std::vector<base::Closure> callbacks =
9359 pending_readpixel_fences_.front()->callbacks;
9360 pending_readpixel_fences_.pop();
9361 for (size_t i = 0; i < callbacks.size(); i++) {
9367 bool GLES2DecoderImpl::HasMoreIdleWork() {
9368 return !pending_readpixel_fences_.empty() ||
9369 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9372 void GLES2DecoderImpl::PerformIdleWork() {
9373 ProcessPendingReadPixels();
9374 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9376 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9377 ProcessFinishedAsyncTransfers();
9380 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9381 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9382 GLenum target = static_cast<GLenum>(c.target);
9383 GLuint client_id = static_cast<GLuint>(c.id);
9384 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9385 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9388 case GL_COMMANDS_ISSUED_CHROMIUM:
9389 case GL_LATENCY_QUERY_CHROMIUM:
9390 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9391 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9392 case GL_GET_ERROR_QUERY_CHROMIUM:
9395 if (!features().occlusion_query_boolean) {
9397 GL_INVALID_OPERATION, "glBeginQueryEXT",
9398 "not enabled for occlusion queries");
9399 return error::kNoError;
9404 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9406 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9407 return error::kNoError;
9410 if (client_id == 0) {
9411 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9412 return error::kNoError;
9415 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9417 // TODO(gman): Decide if we need this check.
9419 // Checks id was made by glGenQueries
9421 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9422 // for all Query ids but from the POV of the command buffer service maybe
9425 // The client can enforce this. I don't think the service cares.
9427 // IdAllocatorInterface* id_allocator =
9428 // group_->GetIdAllocator(id_namespaces::kQueries);
9429 // if (!id_allocator->InUse(client_id)) {
9430 // LOCAL_SET_GL_ERROR(
9431 // GL_INVALID_OPERATION,
9432 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
9433 // return error::kNoError;
9435 query = query_manager_->CreateQuery(
9436 target, client_id, sync_shm_id, sync_shm_offset);
9439 if (query->target() != target) {
9441 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9442 return error::kNoError;
9443 } else if (query->shm_id() != sync_shm_id ||
9444 query->shm_offset() != sync_shm_offset) {
9445 DLOG(ERROR) << "Shared memory used by query not the same as before";
9446 return error::kInvalidArguments;
9449 if (!query_manager_->BeginQuery(query)) {
9450 return error::kOutOfBounds;
9453 state_.current_queries[target] = query;
9454 return error::kNoError;
9457 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9458 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9459 GLenum target = static_cast<GLenum>(c.target);
9460 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9461 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9463 if (it == state_.current_queries.end()) {
9465 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9466 return error::kNoError;
9469 QueryManager::Query* query = it->second.get();
9470 if (!query_manager_->EndQuery(query, submit_count)) {
9471 return error::kOutOfBounds;
9474 query_manager_->ProcessPendingTransferQueries();
9476 state_.current_queries.erase(it);
9477 return error::kNoError;
9480 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9481 GLsizei n, const GLuint* client_ids) {
9482 for (GLsizei ii = 0; ii < n; ++ii) {
9483 if (GetVertexAttribManager(client_ids[ii])) {
9488 if (!features().native_vertex_array_object) {
9490 for (GLsizei ii = 0; ii < n; ++ii) {
9491 CreateVertexAttribManager(client_ids[ii], 0);
9494 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9496 glGenVertexArraysOES(n, service_ids.get());
9497 for (GLsizei ii = 0; ii < n; ++ii) {
9498 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9505 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9506 GLsizei n, const GLuint* client_ids) {
9507 for (GLsizei ii = 0; ii < n; ++ii) {
9508 VertexAttribManager* vao =
9509 GetVertexAttribManager(client_ids[ii]);
9510 if (vao && !vao->IsDeleted()) {
9511 if (state_.vertex_attrib_manager.get() == vao) {
9512 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
9514 RemoveVertexAttribManager(client_ids[ii]);
9519 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9520 VertexAttribManager* vao = NULL;
9521 GLuint service_id = 0;
9522 if (client_id != 0) {
9523 vao = GetVertexAttribManager(client_id);
9525 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9526 // only allows names that have been previously generated. As such, we do
9527 // not generate new names here.
9529 GL_INVALID_OPERATION,
9530 "glBindVertexArrayOES", "bad vertex array id.");
9531 current_decoder_error_ = error::kNoError;
9534 service_id = vao->service_id();
9537 vao = default_vertex_attrib_manager_.get();
9540 // Only set the VAO state if it's changed
9541 if (state_.vertex_attrib_manager.get() != vao) {
9542 state_.vertex_attrib_manager = vao;
9543 if (!features().native_vertex_array_object) {
9544 EmulateVertexArrayState();
9546 glBindVertexArrayOES(service_id);
9551 // Used when OES_vertex_array_object isn't natively supported
9552 void GLES2DecoderImpl::EmulateVertexArrayState() {
9553 // Setup the Vertex attribute state
9554 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9555 RestoreStateForAttrib(vv);
9558 // Setup the element buffer
9559 Buffer* element_array_buffer =
9560 state_.vertex_attrib_manager->element_array_buffer();
9561 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9562 element_array_buffer ? element_array_buffer->service_id() : 0);
9565 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9566 const VertexAttribManager* vao =
9567 GetVertexAttribManager(client_id);
9568 return vao && vao->IsValid() && !vao->IsDeleted();
9571 #if defined(OS_MACOSX)
9572 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9573 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9575 if (it != texture_to_io_surface_map_.end()) {
9576 // Found a previous IOSurface bound to this texture; release it.
9577 CFTypeRef surface = it->second;
9579 texture_to_io_surface_map_.erase(it);
9584 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9585 GLenum target, GLsizei width, GLsizei height,
9586 GLuint io_surface_id, GLuint plane) {
9587 #if defined(OS_MACOSX)
9588 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9590 GL_INVALID_OPERATION,
9591 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9595 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9596 if (!surface_support) {
9598 GL_INVALID_OPERATION,
9599 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
9603 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9604 // This might be supported in the future, and if we could require
9605 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9606 // could delete a lot of code. For now, perform strict validation so we
9607 // know what's going on.
9609 GL_INVALID_OPERATION,
9610 "glTexImageIOSurface2DCHROMIUM",
9611 "requires TEXTURE_RECTANGLE_ARB target");
9615 // Default target might be conceptually valid, but disallow it to avoid
9617 TextureRef* texture_ref =
9618 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9621 GL_INVALID_OPERATION,
9622 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9626 // Look up the new IOSurface. Note that because of asynchrony
9627 // between processes this might fail; during live resizing the
9628 // plugin process might allocate and release an IOSurface before
9629 // this process gets a chance to look it up. Hold on to any old
9630 // IOSurface in this case.
9631 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9634 GL_INVALID_OPERATION,
9635 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9639 // Release any IOSurface previously bound to this texture.
9640 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9642 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9643 texture_to_io_surface_map_.insert(
9644 std::make_pair(texture_ref->service_id(), surface));
9646 CGLContextObj context =
9647 static_cast<CGLContextObj>(context_->GetHandle());
9649 CGLError err = surface_support->CGLTexImageIOSurface2D(
9656 GL_UNSIGNED_INT_8_8_8_8_REV,
9660 if (err != kCGLNoError) {
9662 GL_INVALID_OPERATION,
9663 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9667 texture_manager()->SetLevelInfo(
9668 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9669 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9672 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9673 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9677 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9678 switch (internalformat) {
9689 case GL_LUMINANCE8_ALPHA8_EXT:
9690 return GL_LUMINANCE_ALPHA;
9691 case GL_LUMINANCE8_EXT:
9692 return GL_LUMINANCE;
9695 case GL_RGBA32F_EXT:
9699 case GL_ALPHA32F_EXT:
9701 case GL_LUMINANCE32F_EXT:
9702 return GL_LUMINANCE;
9703 case GL_LUMINANCE_ALPHA32F_EXT:
9704 return GL_LUMINANCE_ALPHA;
9705 case GL_RGBA16F_EXT:
9709 case GL_ALPHA16F_EXT:
9711 case GL_LUMINANCE16F_EXT:
9712 return GL_LUMINANCE;
9713 case GL_LUMINANCE_ALPHA16F_EXT:
9714 return GL_LUMINANCE_ALPHA;
9722 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9723 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9724 GLenum internal_format, GLenum dest_type) {
9725 TextureRef* dest_texture_ref = GetTexture(dest_id);
9726 TextureRef* source_texture_ref = GetTexture(source_id);
9728 if (!source_texture_ref || !dest_texture_ref) {
9730 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9734 if (GL_TEXTURE_2D != target) {
9736 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9740 Texture* source_texture = source_texture_ref->texture();
9741 Texture* dest_texture = dest_texture_ref->texture();
9742 if (dest_texture->target() != GL_TEXTURE_2D ||
9743 (source_texture->target() != GL_TEXTURE_2D &&
9744 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9745 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9746 "glCopyTextureCHROMIUM",
9747 "invalid texture target binding");
9751 int source_width, source_height, dest_width, dest_height;
9753 gfx::GLImage* image =
9754 source_texture->GetLevelImage(source_texture->target(), 0);
9756 gfx::Size size = image->GetSize();
9757 source_width = size.width();
9758 source_height = size.height();
9759 if (source_width <= 0 || source_height <= 0) {
9762 "glCopyTextureChromium", "invalid image size");
9766 if (!source_texture->GetLevelSize(
9767 source_texture->target(), 0, &source_width, &source_height)) {
9768 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9769 "glCopyTextureChromium",
9770 "source texture has no level 0");
9774 // Check that this type of texture is allowed.
9775 if (!texture_manager()->ValidForTarget(
9776 source_texture->target(), level, source_width, source_height, 1)) {
9778 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9783 // Clear the source texture if necessary.
9784 if (!texture_manager()->ClearTextureLevel(
9785 this, source_texture_ref, source_texture->target(), 0)) {
9787 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
9791 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9792 // needed because it takes 10s of milliseconds to initialize.
9793 if (!copy_texture_CHROMIUM_.get()) {
9794 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9795 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9796 copy_texture_CHROMIUM_->Initialize(this);
9797 RestoreCurrentFramebufferBindings();
9798 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9802 GLenum dest_type_previous;
9803 GLenum dest_internal_format;
9804 bool dest_level_defined = dest_texture->GetLevelSize(
9805 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9807 if (dest_level_defined) {
9808 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9809 &dest_internal_format);
9812 // Resize the destination texture to the dimensions of the source texture.
9813 if (!dest_level_defined || dest_width != source_width ||
9814 dest_height != source_height ||
9815 dest_internal_format != internal_format ||
9816 dest_type_previous != dest_type) {
9817 // Ensure that the glTexImage2D succeeds.
9818 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9819 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9821 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9822 0, internal_format, dest_type, NULL);
9823 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9824 if (error != GL_NO_ERROR) {
9825 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
9829 texture_manager()->SetLevelInfo(
9830 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9831 source_height, 1, 0, internal_format, dest_type, true);
9833 texture_manager()->SetLevelCleared(
9834 dest_texture_ref, GL_TEXTURE_2D, level, true);
9837 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9839 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9840 // before presenting.
9841 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9842 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9843 // instead of using default matrix crbug.com/226218.
9844 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9845 0.0f, 1.0f, 0.0f, 0.0f,
9846 0.0f, 0.0f, 1.0f, 0.0f,
9847 0.0f, 0.0f, 0.0f, 1.0f};
9848 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9850 source_texture->target(),
9851 dest_texture->target(),
9852 source_texture->service_id(),
9853 dest_texture->service_id(), level,
9854 source_width, source_height,
9856 unpack_premultiply_alpha_,
9857 unpack_unpremultiply_alpha_,
9860 copy_texture_CHROMIUM_->DoCopyTexture(
9862 source_texture->target(),
9863 dest_texture->target(),
9864 source_texture->service_id(),
9865 dest_texture->service_id(), level,
9866 source_width, source_height,
9868 unpack_premultiply_alpha_,
9869 unpack_unpremultiply_alpha_);
9872 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
9875 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9876 switch (internalformat) {
9878 return GL_UNSIGNED_SHORT_5_6_5;
9880 return GL_UNSIGNED_SHORT_4_4_4_4;
9882 return GL_UNSIGNED_SHORT_5_5_5_1;
9884 return GL_UNSIGNED_BYTE;
9886 return GL_UNSIGNED_BYTE;
9887 case GL_LUMINANCE8_ALPHA8_EXT:
9888 return GL_UNSIGNED_BYTE;
9889 case GL_LUMINANCE8_EXT:
9890 return GL_UNSIGNED_BYTE;
9892 return GL_UNSIGNED_BYTE;
9893 case GL_RGBA32F_EXT:
9897 case GL_ALPHA32F_EXT:
9899 case GL_LUMINANCE32F_EXT:
9901 case GL_LUMINANCE_ALPHA32F_EXT:
9903 case GL_RGBA16F_EXT:
9904 return GL_HALF_FLOAT_OES;
9906 return GL_HALF_FLOAT_OES;
9907 case GL_ALPHA16F_EXT:
9908 return GL_HALF_FLOAT_OES;
9909 case GL_LUMINANCE16F_EXT:
9910 return GL_HALF_FLOAT_OES;
9911 case GL_LUMINANCE_ALPHA16F_EXT:
9912 return GL_HALF_FLOAT_OES;
9914 return GL_UNSIGNED_BYTE;
9920 void GLES2DecoderImpl::DoTexStorage2DEXT(
9923 GLenum internal_format,
9926 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
9927 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
9928 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
9930 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
9933 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9937 GL_INVALID_OPERATION,
9938 "glTexStorage2DEXT", "unknown texture for target");
9941 Texture* texture = texture_ref->texture();
9942 if (texture->IsAttachedToFramebuffer()) {
9943 framebuffer_state_.clear_state_dirty = true;
9945 if (texture->IsImmutable()) {
9947 GL_INVALID_OPERATION,
9948 "glTexStorage2DEXT", "texture is immutable");
9952 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9953 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9956 GLsizei level_width = width;
9957 GLsizei level_height = height;
9958 uint32 estimated_size = 0;
9959 for (int ii = 0; ii < levels; ++ii) {
9960 uint32 level_size = 0;
9961 if (!GLES2Util::ComputeImageDataSizes(
9962 level_width, level_height, format, type, state_.unpack_alignment,
9963 &estimated_size, NULL, NULL) ||
9964 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
9966 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
9969 level_width = std::max(1, level_width >> 1);
9970 level_height = std::max(1, level_height >> 1);
9972 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9974 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
9979 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
9980 glTexStorage2DEXT(target, levels, internal_format, width, height);
9981 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
9982 if (error == GL_NO_ERROR) {
9983 GLsizei level_width = width;
9984 GLsizei level_height = height;
9985 for (int ii = 0; ii < levels; ++ii) {
9986 texture_manager()->SetLevelInfo(
9987 texture_ref, target, ii, format,
9988 level_width, level_height, 1, 0, format, type, false);
9989 level_width = std::max(1, level_width >> 1);
9990 level_height = std::max(1, level_height >> 1);
9992 texture->SetImmutable(true);
9996 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
9997 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
9998 return error::kUnknownCommand;
10001 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10002 const GLbyte* data) {
10003 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10004 "context", logger_.GetLogPrefix(),
10005 "mailbox[0]", static_cast<unsigned char>(data[0]));
10007 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10008 DLOG_IF(ERROR, !mailbox.Verify()) << "ProduceTextureCHROMIUM was passed a "
10009 "mailbox that was not generated by "
10010 "GenMailboxCHROMIUM.";
10012 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10014 if (!texture_ref) {
10015 LOCAL_SET_GL_ERROR(
10016 GL_INVALID_OPERATION,
10017 "glProduceTextureCHROMIUM", "unknown texture for target");
10021 Texture* produced = texture_manager()->Produce(texture_ref);
10023 LOCAL_SET_GL_ERROR(
10024 GL_INVALID_OPERATION,
10025 "glProduceTextureCHROMIUM", "invalid texture");
10029 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10032 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10033 const GLbyte* data) {
10034 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10035 "context", logger_.GetLogPrefix(),
10036 "mailbox[0]", static_cast<unsigned char>(data[0]));
10037 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10038 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10039 "mailbox that was not generated by "
10040 "GenMailboxCHROMIUM.";
10042 scoped_refptr<TextureRef> texture_ref =
10043 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10044 if (!texture_ref.get()) {
10045 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10046 "glConsumeTextureCHROMIUM",
10047 "unknown texture for target");
10050 GLuint client_id = texture_ref->client_id();
10052 LOCAL_SET_GL_ERROR(
10053 GL_INVALID_OPERATION,
10054 "glConsumeTextureCHROMIUM", "unknown texture for target");
10057 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10059 LOCAL_SET_GL_ERROR(
10060 GL_INVALID_OPERATION,
10061 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10064 if (texture->target() != target) {
10065 LOCAL_SET_GL_ERROR(
10066 GL_INVALID_OPERATION,
10067 "glConsumeTextureCHROMIUM", "invalid target");
10071 DeleteTexturesHelper(1, &client_id);
10072 texture_ref = texture_manager()->Consume(client_id, texture);
10073 glBindTexture(target, texture_ref->service_id());
10075 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10076 unit.bind_target = target;
10078 case GL_TEXTURE_2D:
10079 unit.bound_texture_2d = texture_ref;
10081 case GL_TEXTURE_CUBE_MAP:
10082 unit.bound_texture_cube_map = texture_ref;
10084 case GL_TEXTURE_EXTERNAL_OES:
10085 unit.bound_texture_external_oes = texture_ref;
10087 case GL_TEXTURE_RECTANGLE_ARB:
10088 unit.bound_texture_rectangle_arb = texture_ref;
10091 NOTREACHED(); // Validation should prevent us getting here.
10096 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10097 GLsizei length, const GLchar* marker) {
10101 debug_marker_manager_.SetMarker(
10102 length ? std::string(marker, length) : std::string(marker));
10105 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10106 GLsizei length, const GLchar* marker) {
10110 std::string name = length ? std::string(marker, length) : std::string(marker);
10111 debug_marker_manager_.PushGroup(name);
10112 gpu_tracer_->Begin(name, kTraceGroupMarker);
10115 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10116 debug_marker_manager_.PopGroup();
10117 gpu_tracer_->End(kTraceGroupMarker);
10120 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10121 GLenum target, GLint image_id) {
10122 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10124 if (target == GL_TEXTURE_CUBE_MAP) {
10125 LOCAL_SET_GL_ERROR(
10127 "glBindTexImage2DCHROMIUM", "invalid target");
10131 // Default target might be conceptually valid, but disallow it to avoid
10133 TextureRef* texture_ref =
10134 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10135 if (!texture_ref) {
10136 LOCAL_SET_GL_ERROR(
10137 GL_INVALID_OPERATION,
10138 "glBindTexImage2DCHROMIUM", "no texture bound");
10142 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10144 LOCAL_SET_GL_ERROR(
10145 GL_INVALID_OPERATION,
10146 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10151 ScopedGLErrorSuppressor suppressor(
10152 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10153 if (!gl_image->BindTexImage(target)) {
10154 LOCAL_SET_GL_ERROR(
10155 GL_INVALID_OPERATION,
10156 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10161 gfx::Size size = gl_image->GetSize();
10162 texture_manager()->SetLevelInfo(
10163 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10164 GL_RGBA, GL_UNSIGNED_BYTE, true);
10165 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10168 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10169 GLenum target, GLint image_id) {
10170 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10172 // Default target might be conceptually valid, but disallow it to avoid
10174 TextureRef* texture_ref =
10175 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10176 if (!texture_ref) {
10177 LOCAL_SET_GL_ERROR(
10178 GL_INVALID_OPERATION,
10179 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10183 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10185 LOCAL_SET_GL_ERROR(
10186 GL_INVALID_OPERATION,
10187 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10191 // Do nothing when image is not currently bound.
10192 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10196 ScopedGLErrorSuppressor suppressor(
10197 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10198 gl_image->ReleaseTexImage(target);
10201 texture_manager()->SetLevelInfo(
10202 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10203 GL_RGBA, GL_UNSIGNED_BYTE, false);
10206 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10207 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10208 Bucket* bucket = GetBucket(c.bucket_id);
10209 if (!bucket || bucket->size() == 0) {
10210 return error::kInvalidArguments;
10212 std::string command_name;
10213 if (!bucket->GetAsString(&command_name)) {
10214 return error::kInvalidArguments;
10216 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10217 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10218 LOCAL_SET_GL_ERROR(
10219 GL_INVALID_OPERATION,
10220 "glTraceBeginCHROMIUM", "unable to create begin trace");
10221 return error::kNoError;
10223 return error::kNoError;
10226 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10227 if (gpu_tracer_->CurrentName().empty()) {
10228 LOCAL_SET_GL_ERROR(
10229 GL_INVALID_OPERATION,
10230 "glTraceEndCHROMIUM", "no trace begin found");
10233 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10234 gpu_tracer_->End(kTraceCHROMIUM);
10237 void GLES2DecoderImpl::DoDrawBuffersEXT(
10238 GLsizei count, const GLenum* bufs) {
10239 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10240 LOCAL_SET_GL_ERROR(
10242 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10246 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10248 for (GLsizei i = 0; i < count; ++i) {
10249 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10250 bufs[i] != GL_NONE) {
10251 LOCAL_SET_GL_ERROR(
10252 GL_INVALID_OPERATION,
10253 "glDrawBuffersEXT",
10254 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10258 glDrawBuffersARB(count, bufs);
10259 framebuffer->SetDrawBuffers(count, bufs);
10260 } else { // backbuffer
10262 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10263 LOCAL_SET_GL_ERROR(
10264 GL_INVALID_OPERATION,
10265 "glDrawBuffersEXT",
10266 "more than one buffer or bufs not GL_NONE or GL_BACK");
10269 GLenum mapped_buf = bufs[0];
10270 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10271 bufs[0] == GL_BACK) {
10272 mapped_buf = GL_COLOR_ATTACHMENT0;
10274 glDrawBuffersARB(count, &mapped_buf);
10275 group_->set_draw_buffer(bufs[0]);
10279 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10280 const char* function_name,
10281 TextureRef* texture_ref,
10284 const void * data) {
10285 // We only support async uploads to 2D textures for now.
10286 if (GL_TEXTURE_2D != target) {
10287 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10290 // We only support uploads to level zero for now.
10292 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10295 // A transfer buffer must be bound, even for asyncTexImage2D.
10296 if (data == NULL) {
10297 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10300 // We only support one async transfer in progress.
10301 if (!texture_ref ||
10302 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10303 LOCAL_SET_GL_ERROR(
10304 GL_INVALID_OPERATION,
10305 function_name, "transfer already in progress");
10311 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10312 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10313 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10314 GLenum target = static_cast<GLenum>(c.target);
10315 GLint level = static_cast<GLint>(c.level);
10316 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10317 // unsigned integer for internalformat.
10318 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10319 GLsizei width = static_cast<GLsizei>(c.width);
10320 GLsizei height = static_cast<GLsizei>(c.height);
10321 GLint border = static_cast<GLint>(c.border);
10322 GLenum format = static_cast<GLenum>(c.format);
10323 GLenum type = static_cast<GLenum>(c.type);
10324 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10325 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10326 uint32 pixels_size;
10328 // TODO(epenner): Move this and copies of this memory validation
10329 // into ValidateTexImage2D step.
10330 if (!GLES2Util::ComputeImageDataSizes(
10331 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10333 return error::kOutOfBounds;
10335 const void* pixels = NULL;
10336 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10337 pixels = GetSharedMemoryAs<const void*>(
10338 pixels_shm_id, pixels_shm_offset, pixels_size);
10340 return error::kOutOfBounds;
10344 TextureManager::DoTextImage2DArguments args = {
10345 target, level, internal_format, width, height, border, format, type,
10346 pixels, pixels_size};
10347 TextureRef* texture_ref;
10348 // All the normal glTexSubImage2D validation.
10349 if (!texture_manager()->ValidateTexImage2D(
10350 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10351 return error::kNoError;
10354 // Extra async validation.
10355 Texture* texture = texture_ref->texture();
10356 if (!ValidateAsyncTransfer(
10357 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10358 return error::kNoError;
10360 // Don't allow async redefinition of a textures.
10361 if (texture->IsDefined()) {
10362 LOCAL_SET_GL_ERROR(
10363 GL_INVALID_OPERATION,
10364 "glAsyncTexImage2DCHROMIUM", "already defined");
10365 return error::kNoError;
10368 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10369 LOCAL_SET_GL_ERROR(
10370 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10371 return error::kNoError;
10374 // We know the memory/size is safe, so get the real shared memory since
10375 // it might need to be duped to prevent use-after-free of the memory.
10376 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
10377 base::SharedMemory* shared_memory = buffer.shared_memory;
10378 uint32 shm_size = buffer.size;
10379 uint32 shm_data_offset = c.pixels_shm_offset;
10380 uint32 shm_data_size = pixels_size;
10382 // Setup the parameters.
10383 AsyncTexImage2DParams tex_params = {
10384 target, level, static_cast<GLenum>(internal_format),
10385 width, height, border, format, type};
10386 AsyncMemoryParams mem_params = {
10387 shared_memory, shm_size, shm_data_offset, shm_data_size};
10389 // Set up the async state if needed, and make the texture
10390 // immutable so the async state stays valid. The level info
10391 // is set up lazily when the transfer completes.
10392 AsyncPixelTransferDelegate* delegate =
10393 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10395 texture->SetImmutable(true);
10397 delegate->AsyncTexImage2D(
10400 base::Bind(&TextureManager::SetLevelInfoFromParams,
10401 // The callback is only invoked if the transfer delegate still
10402 // exists, which implies through manager->texture_ref->state
10403 // ownership that both of these pointers are valid.
10404 base::Unretained(texture_manager()),
10405 base::Unretained(texture_ref),
10407 return error::kNoError;
10410 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10411 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10412 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10413 GLenum target = static_cast<GLenum>(c.target);
10414 GLint level = static_cast<GLint>(c.level);
10415 GLint xoffset = static_cast<GLint>(c.xoffset);
10416 GLint yoffset = static_cast<GLint>(c.yoffset);
10417 GLsizei width = static_cast<GLsizei>(c.width);
10418 GLsizei height = static_cast<GLsizei>(c.height);
10419 GLenum format = static_cast<GLenum>(c.format);
10420 GLenum type = static_cast<GLenum>(c.type);
10422 // TODO(epenner): Move this and copies of this memory validation
10423 // into ValidateTexSubImage2D step.
10425 if (!GLES2Util::ComputeImageDataSizes(
10426 width, height, format, type, state_.unpack_alignment, &data_size,
10428 return error::kOutOfBounds;
10430 const void* pixels = GetSharedMemoryAs<const void*>(
10431 c.data_shm_id, c.data_shm_offset, data_size);
10433 // All the normal glTexSubImage2D validation.
10434 error::Error error = error::kNoError;
10435 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10436 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10440 // Extra async validation.
10441 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10443 Texture* texture = texture_ref->texture();
10444 if (!ValidateAsyncTransfer(
10445 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10446 return error::kNoError;
10448 // Guarantee async textures are always 'cleared' as follows:
10449 // - AsyncTexImage2D can not redefine an existing texture
10450 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10451 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10452 // - Textures become immutable after an async call.
10453 // This way we know in all cases that an async texture is always clear.
10454 if (!texture->SafeToRenderFrom()) {
10455 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10457 LOCAL_SET_GL_ERROR(
10459 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10460 return error::kNoError;
10464 // We know the memory/size is safe, so get the real shared memory since
10465 // it might need to be duped to prevent use-after-free of the memory.
10466 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
10467 base::SharedMemory* shared_memory = buffer.shared_memory;
10468 uint32 shm_size = buffer.size;
10469 uint32 shm_data_offset = c.data_shm_offset;
10470 uint32 shm_data_size = data_size;
10472 // Setup the parameters.
10473 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10474 width, height, format, type};
10475 AsyncMemoryParams mem_params = {shared_memory, shm_size,
10476 shm_data_offset, shm_data_size};
10477 AsyncPixelTransferDelegate* delegate =
10478 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10480 // TODO(epenner): We may want to enforce exclusive use
10481 // of async APIs in which case this should become an error,
10482 // (the texture should have been async defined).
10483 AsyncTexImage2DParams define_params = {target, level,
10485 texture->GetLevelSize(target, level, &define_params.width,
10486 &define_params.height);
10487 texture->GetLevelType(target, level, &define_params.type,
10488 &define_params.internal_format);
10489 // Set up the async state if needed, and make the texture
10490 // immutable so the async state stays valid.
10491 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10492 texture_ref, define_params);
10493 texture->SetImmutable(true);
10496 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10497 return error::kNoError;
10500 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10501 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10502 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10503 GLenum target = static_cast<GLenum>(c.target);
10505 if (GL_TEXTURE_2D != target) {
10506 LOCAL_SET_GL_ERROR(
10507 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10508 return error::kNoError;
10510 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10512 if (!texture_ref) {
10513 LOCAL_SET_GL_ERROR(
10514 GL_INVALID_OPERATION,
10515 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10516 return error::kNoError;
10518 AsyncPixelTransferDelegate* delegate =
10519 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10521 LOCAL_SET_GL_ERROR(
10522 GL_INVALID_OPERATION,
10523 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10524 return error::kNoError;
10526 delegate->WaitForTransferCompletion();
10527 ProcessFinishedAsyncTransfers();
10528 return error::kNoError;
10531 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10532 TextureRef* texture_ref) {
10533 Texture* texture = texture_ref->texture();
10534 DoDidUseTexImageIfNeeded(texture, texture->target());
10537 // Include the auto-generated part of this file. We split this because it means
10538 // we can easily edit the non-auto generated parts right here in this file
10539 // instead of having to edit some template or the code generator.
10540 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10542 } // namespace gles2