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 2D 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 ScopedTexture2DBinder {
307 ScopedTexture2DBinder(ContextState* state, GLuint id);
308 ~ScopedTexture2DBinder();
311 ContextState* state_;
312 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
315 // Temporarily changes a decoder's bound render buffer and restore it when this
316 // object goes out of scope.
317 class ScopedRenderBufferBinder {
319 ScopedRenderBufferBinder(ContextState* state, GLuint id);
320 ~ScopedRenderBufferBinder();
323 ContextState* state_;
324 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
327 // Temporarily changes a decoder's bound frame buffer and restore it when this
328 // object goes out of scope.
329 class ScopedFrameBufferBinder {
331 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
332 ~ScopedFrameBufferBinder();
335 GLES2DecoderImpl* decoder_;
336 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
339 // Temporarily changes a decoder's bound frame buffer to a resolved version of
340 // the multisampled offscreen render buffer if that buffer is multisampled, and,
341 // if it is bound or enforce_internal_framebuffer is true. If internal is
342 // true, the resolved framebuffer is not visible to the parent.
343 class ScopedResolvedFrameBufferBinder {
345 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
346 bool enforce_internal_framebuffer,
348 ~ScopedResolvedFrameBufferBinder();
351 GLES2DecoderImpl* decoder_;
352 bool resolve_and_bind_;
353 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
356 // Encapsulates an OpenGL texture.
359 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
362 // Create a new render texture.
365 // Set the initial size and format of a render texture or resize it.
366 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
368 // Copy the contents of the currently bound frame buffer.
369 void Copy(const gfx::Size& size, GLenum format);
371 // Destroy the render texture. This must be explicitly called before
372 // destroying this object.
375 // Invalidate the texture. This can be used when a context is lost and it is
376 // not possible to make it current in order to free the resource.
383 gfx::Size size() const {
388 MemoryTypeTracker memory_tracker_;
389 ContextState* state_;
390 size_t bytes_allocated_;
393 DISALLOW_COPY_AND_ASSIGN(BackTexture);
396 // Encapsulates an OpenGL render buffer of any format.
397 class BackRenderbuffer {
399 explicit BackRenderbuffer(
400 RenderbufferManager* renderbuffer_manager,
401 MemoryTracker* memory_tracker,
402 ContextState* state);
405 // Create a new render buffer.
408 // Set the initial size and format of a render buffer or resize it.
409 bool AllocateStorage(const FeatureInfo* feature_info,
410 const gfx::Size& size,
414 // Destroy the render buffer. This must be explicitly called before destroying
418 // Invalidate the render buffer. This can be used when a context is lost and
419 // it is not possible to make it current in order to free the resource.
427 RenderbufferManager* renderbuffer_manager_;
428 MemoryTypeTracker memory_tracker_;
429 ContextState* state_;
430 size_t bytes_allocated_;
432 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
435 // Encapsulates an OpenGL frame buffer.
436 class BackFramebuffer {
438 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
441 // Create a new frame buffer.
444 // Attach a color render buffer to a frame buffer.
445 void AttachRenderTexture(BackTexture* texture);
447 // Attach a render buffer to a frame buffer. Note that this unbinds any
448 // currently bound frame buffer.
449 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
451 // Destroy the frame buffer. This must be explicitly called before destroying
455 // Invalidate the frame buffer. This can be used when a context is lost and it
456 // is not possible to make it current in order to free the resource.
459 // See glCheckFramebufferStatusEXT.
460 GLenum CheckStatus();
467 GLES2DecoderImpl* decoder_;
469 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
472 struct FenceCallback {
473 explicit FenceCallback()
474 : fence(gfx::GLFence::Create()) {
477 std::vector<base::Closure> callbacks;
478 scoped_ptr<gfx::GLFence> fence;
481 // } // anonymous namespace.
483 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
484 uint32* service_texture_id) {
488 GLES2Decoder::GLES2Decoder()
489 : initialized_(false),
491 log_commands_(false) {
494 GLES2Decoder::~GLES2Decoder() {
497 void GLES2Decoder::BeginDecoding() {}
499 void GLES2Decoder::EndDecoding() {}
501 // This class implements GLES2Decoder so we don't have to expose all the GLES2
502 // cmd stuff to outside this class.
503 class GLES2DecoderImpl : public GLES2Decoder,
504 public FramebufferManager::TextureDetachObserver {
506 // Used by PrepForSetUniformByLocation to validate types.
507 struct BaseUniformInfo {
508 const GLenum* const valid_types;
509 size_t num_valid_types;
512 explicit GLES2DecoderImpl(ContextGroup* group);
513 virtual ~GLES2DecoderImpl();
515 // Overridden from AsyncAPIInterface.
516 virtual Error DoCommand(unsigned int command,
517 unsigned int arg_count,
518 const void* args) OVERRIDE;
520 // Overridden from AsyncAPIInterface.
521 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
523 // Overridden from GLES2Decoder.
524 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
525 const scoped_refptr<gfx::GLContext>& context,
527 const gfx::Size& size,
528 const DisallowedFeatures& disallowed_features,
529 const std::vector<int32>& attribs) OVERRIDE;
530 virtual void Destroy(bool have_context) OVERRIDE;
531 virtual void SetSurface(
532 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
533 virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
534 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
535 void UpdateParentTextureInfo();
536 virtual bool MakeCurrent() OVERRIDE;
537 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
538 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
539 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
540 virtual Capabilities GetCapabilities() OVERRIDE;
541 virtual void RestoreState(const ContextState* prev_state) const OVERRIDE;
543 virtual void RestoreActiveTexture() const OVERRIDE {
544 state_.RestoreActiveTexture();
546 virtual void RestoreAllTextureUnitBindings(
547 const ContextState* prev_state) const OVERRIDE {
548 state_.RestoreAllTextureUnitBindings(prev_state);
550 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
551 state_.RestoreAttribute(index);
553 virtual void RestoreBufferBindings() const OVERRIDE {
554 state_.RestoreBufferBindings();
556 virtual void RestoreGlobalState() const OVERRIDE {
557 state_.RestoreGlobalState();
559 virtual void RestoreProgramBindings() const OVERRIDE {
560 state_.RestoreProgramBindings();
562 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
563 state_.RestoreTextureUnitBindings(unit, NULL);
565 virtual void RestoreFramebufferBindings() const OVERRIDE;
566 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
568 virtual QueryManager* GetQueryManager() OVERRIDE {
569 return query_manager_.get();
571 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
572 return vertex_array_manager_.get();
574 virtual bool ProcessPendingQueries() OVERRIDE;
575 virtual bool HasMoreIdleWork() OVERRIDE;
576 virtual void PerformIdleWork() OVERRIDE;
578 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
580 virtual void SetResizeCallback(
581 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
583 virtual Logger* GetLogger() OVERRIDE;
585 virtual void BeginDecoding() OVERRIDE;
586 virtual void EndDecoding() OVERRIDE;
588 virtual ErrorState* GetErrorState() OVERRIDE;
589 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
591 virtual void SetShaderCacheCallback(
592 const ShaderCacheCallback& callback) OVERRIDE;
593 virtual void SetWaitSyncPointCallback(
594 const WaitSyncPointCallback& callback) OVERRIDE;
596 virtual AsyncPixelTransferManager*
597 GetAsyncPixelTransferManager() OVERRIDE;
598 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
599 virtual void SetAsyncPixelTransferManagerForTest(
600 AsyncPixelTransferManager* manager) OVERRIDE;
601 void ProcessFinishedAsyncTransfers();
603 virtual bool GetServiceTextureId(uint32 client_texture_id,
604 uint32* service_texture_id) OVERRIDE;
606 virtual uint32 GetTextureUploadCount() OVERRIDE;
607 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
608 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
609 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
611 // Restores the current state to the user's settings.
612 void RestoreCurrentFramebufferBindings();
614 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
615 void ApplyDirtyState();
617 // These check the state of the currently bound framebuffer or the
618 // backbuffer if no framebuffer is bound.
619 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
620 // check with all attached and enabled color attachments.
621 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
622 bool BoundFramebufferHasDepthAttachment();
623 bool BoundFramebufferHasStencilAttachment();
625 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
627 // Overridden from FramebufferManager::TextureDetachObserver:
628 virtual void OnTextureRefDetachedFromFramebuffer(
629 TextureRef* texture) OVERRIDE;
631 // Helpers to facilitate calling into compatible extensions.
632 static void RenderbufferStorageMultisampleHelper(
633 const FeatureInfo* feature_info,
636 GLenum internal_format,
640 void BlitFramebufferHelper(GLint srcX0,
652 friend class ScopedFrameBufferBinder;
653 friend class ScopedResolvedFrameBufferBinder;
654 friend class BackFramebuffer;
656 // Initialize or re-initialize the shader translator.
657 bool InitializeShaderTranslator();
659 void UpdateCapabilities();
661 // Helpers for the glGen and glDelete functions.
662 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
663 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
664 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
665 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
666 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
667 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
668 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
669 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
670 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
671 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
672 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
673 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
676 void OnFboChanged() const;
677 void OnUseFramebuffer() const;
679 // TODO(gman): Cache these pointers?
680 BufferManager* buffer_manager() {
681 return group_->buffer_manager();
684 RenderbufferManager* renderbuffer_manager() {
685 return group_->renderbuffer_manager();
688 FramebufferManager* framebuffer_manager() {
689 return group_->framebuffer_manager();
692 ProgramManager* program_manager() {
693 return group_->program_manager();
696 ShaderManager* shader_manager() {
697 return group_->shader_manager();
700 const TextureManager* texture_manager() const {
701 return group_->texture_manager();
704 TextureManager* texture_manager() {
705 return group_->texture_manager();
708 MailboxManager* mailbox_manager() {
709 return group_->mailbox_manager();
712 ImageManager* image_manager() {
713 return group_->image_manager();
716 VertexArrayManager* vertex_array_manager() {
717 return vertex_array_manager_.get();
720 MemoryTracker* memory_tracker() {
721 return group_->memory_tracker();
724 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
725 MemoryTracker* tracker = memory_tracker();
727 return tracker->EnsureGPUMemoryAvailable(estimated_size);
732 bool IsOffscreenBufferMultisampled() const {
733 return offscreen_target_samples_ > 1;
736 // Creates a Texture for the given texture.
737 TextureRef* CreateTexture(
738 GLuint client_id, GLuint service_id) {
739 return texture_manager()->CreateTexture(client_id, service_id);
742 // Gets the texture info for the given texture. Returns NULL if none exists.
743 TextureRef* GetTexture(GLuint client_id) const {
744 return texture_manager()->GetTexture(client_id);
747 // Deletes the texture info for the given texture.
748 void RemoveTexture(GLuint client_id) {
749 texture_manager()->RemoveTexture(client_id);
752 // Get the size (in pixels) of the currently bound frame buffer (either FBO
753 // or regular back buffer).
754 gfx::Size GetBoundReadFrameBufferSize();
756 // Get the format of the currently bound frame buffer (either FBO or regular
758 GLenum GetBoundReadFrameBufferTextureType();
759 GLenum GetBoundReadFrameBufferInternalFormat();
760 GLenum GetBoundDrawFrameBufferInternalFormat();
762 // Wrapper for CompressedTexImage2D commands.
763 error::Error DoCompressedTexImage2D(
766 GLenum internal_format,
773 // Wrapper for CompressedTexSubImage2D.
774 void DoCompressedTexSubImage2D(
785 // Wrapper for CopyTexImage2D.
786 void DoCopyTexImage2D(
789 GLenum internal_format,
796 // Wrapper for SwapBuffers.
797 void DoSwapBuffers();
799 // Wrapper for CopyTexSubImage2D.
800 void DoCopyTexSubImage2D(
810 // Validation for TexSubImage2D.
811 bool ValidateTexSubImage2D(
813 const char* function_name,
824 // Wrapper for TexSubImage2D.
825 error::Error DoTexSubImage2D(
836 // Extra validation for async tex(Sub)Image2D.
837 bool ValidateAsyncTransfer(
838 const char* function_name,
839 TextureRef* texture_ref,
844 // Wrapper for TexImageIOSurface2DCHROMIUM.
845 void DoTexImageIOSurface2DCHROMIUM(
849 GLuint io_surface_id,
852 void DoCopyTextureCHROMIUM(
857 GLenum internal_format,
860 // Wrapper for TexStorage2DEXT.
861 void DoTexStorage2DEXT(
864 GLenum internal_format,
868 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
869 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
871 void DoBindTexImage2DCHROMIUM(
874 void DoReleaseTexImage2DCHROMIUM(
878 void DoTraceEndCHROMIUM(void);
880 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
882 // Creates a Program for the given program.
883 Program* CreateProgram(
884 GLuint client_id, GLuint service_id) {
885 return program_manager()->CreateProgram(client_id, service_id);
888 // Gets the program info for the given program. Returns NULL if none exists.
889 Program* GetProgram(GLuint client_id) {
890 return program_manager()->GetProgram(client_id);
894 void LogClientServiceMapping(
895 const char* /* function_name */,
896 GLuint /* client_id */,
897 GLuint /* service_id */) {
900 void LogClientServiceForInfo(
901 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
904 void LogClientServiceMapping(
905 const char* function_name, GLuint client_id, GLuint service_id) {
906 if (service_logging_) {
907 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
908 << ": client_id = " << client_id
909 << ", service_id = " << service_id;
913 void LogClientServiceForInfo(
914 T* info, GLuint client_id, const char* function_name) {
916 LogClientServiceMapping(function_name, client_id, info->service_id());
921 // Gets the program info for the given program. If it's not a program
922 // generates a GL error. Returns NULL if not program.
923 Program* GetProgramInfoNotShader(
924 GLuint client_id, const char* function_name) {
925 Program* program = GetProgram(client_id);
927 if (GetShader(client_id)) {
929 GL_INVALID_OPERATION, function_name, "shader passed for program");
931 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
934 LogClientServiceForInfo(program, client_id, function_name);
939 // Creates a Shader for the given shader.
940 Shader* CreateShader(
943 GLenum shader_type) {
944 return shader_manager()->CreateShader(
945 client_id, service_id, shader_type);
948 // Gets the shader info for the given shader. Returns NULL if none exists.
949 Shader* GetShader(GLuint client_id) {
950 return shader_manager()->GetShader(client_id);
953 // Gets the shader info for the given shader. If it's not a shader generates a
954 // GL error. Returns NULL if not shader.
955 Shader* GetShaderInfoNotProgram(
956 GLuint client_id, const char* function_name) {
957 Shader* shader = GetShader(client_id);
959 if (GetProgram(client_id)) {
961 GL_INVALID_OPERATION, function_name, "program passed for shader");
964 GL_INVALID_VALUE, function_name, "unknown shader");
967 LogClientServiceForInfo(shader, client_id, function_name);
971 // Creates a buffer info for the given buffer.
972 void CreateBuffer(GLuint client_id, GLuint service_id) {
973 return buffer_manager()->CreateBuffer(client_id, service_id);
976 // Gets the buffer info for the given buffer.
977 Buffer* GetBuffer(GLuint client_id) {
978 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
982 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
983 // on glDeleteBuffers so we can make sure the user does not try to render
984 // with deleted buffers.
985 void RemoveBuffer(GLuint client_id);
987 // Creates a framebuffer info for the given framebuffer.
988 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
989 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
992 // Gets the framebuffer info for the given framebuffer.
993 Framebuffer* GetFramebuffer(GLuint client_id) {
994 return framebuffer_manager()->GetFramebuffer(client_id);
997 // Removes the framebuffer info for the given framebuffer.
998 void RemoveFramebuffer(GLuint client_id) {
999 framebuffer_manager()->RemoveFramebuffer(client_id);
1002 // Creates a renderbuffer info for the given renderbuffer.
1003 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1004 return renderbuffer_manager()->CreateRenderbuffer(
1005 client_id, service_id);
1008 // Gets the renderbuffer info for the given renderbuffer.
1009 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1010 return renderbuffer_manager()->GetRenderbuffer(client_id);
1013 // Removes the renderbuffer info for the given renderbuffer.
1014 void RemoveRenderbuffer(GLuint client_id) {
1015 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1018 // Gets the vertex attrib manager for the given vertex array.
1019 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1020 VertexAttribManager* info =
1021 vertex_array_manager()->GetVertexAttribManager(client_id);
1025 // Removes the vertex attrib manager for the given vertex array.
1026 void RemoveVertexAttribManager(GLuint client_id) {
1027 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1030 // Creates a vertex attrib manager for the given vertex array.
1031 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1032 return vertex_array_manager()->CreateVertexAttribManager(
1033 client_id, service_id, group_->max_vertex_attribs());
1036 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1037 void DoBindUniformLocationCHROMIUM(
1038 GLuint client_id, GLint location, const char* name);
1040 error::Error GetAttribLocationHelper(
1041 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1042 const std::string& name_str);
1044 error::Error GetUniformLocationHelper(
1045 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1046 const std::string& name_str);
1048 // Helper for glShaderSource.
1049 error::Error ShaderSourceHelper(
1050 GLuint client_id, const char* data, uint32 data_size);
1052 // Clear any textures used by the current program.
1053 bool ClearUnclearedTextures();
1055 // Clears any uncleared attachments attached to the given frame buffer.
1056 // Returns false if there was a generated GL error.
1057 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1059 // overridden from GLES2Decoder
1060 virtual bool ClearLevel(unsigned service_id,
1061 unsigned bind_target,
1068 bool is_texture_immutable) OVERRIDE;
1070 // Restore all GL state that affects clearing.
1071 void RestoreClearState();
1073 // Remembers the state of some capabilities.
1074 // Returns: true if glEnable/glDisable should actually be called.
1075 bool SetCapabilityState(GLenum cap, bool enabled);
1077 // Check that the currently bound framebuffers are valid.
1078 // Generates GL error if not.
1079 bool CheckBoundFramebuffersValid(const char* func_name);
1081 // Check if a framebuffer meets our requirements.
1082 bool CheckFramebufferValid(
1083 Framebuffer* framebuffer,
1085 const char* func_name);
1087 // Checks if the current program exists and is valid. If not generates the
1088 // appropriate GL error. Returns true if the current program is in a usable
1090 bool CheckCurrentProgram(const char* function_name);
1092 // Checks if the current program exists and is valid and that location is not
1093 // -1. If the current program is not valid generates the appropriate GL
1094 // error. Returns true if the current program is in a usable state and
1095 // location is not -1.
1096 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1098 // Gets the type of a uniform for a location in the current program. Sets GL
1099 // errors if the current program is not valid. Returns true if the current
1100 // program is valid and the location exists. Adjusts count so it
1101 // does not overflow the uniform.
1102 bool PrepForSetUniformByLocation(
1103 GLint fake_location, const char* function_name,
1104 const BaseUniformInfo& base_info,
1105 GLint* real_location, GLenum* type, GLsizei* count);
1107 // Gets the service id for any simulated backbuffer fbo.
1108 GLuint GetBackbufferServiceId() const;
1110 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1111 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1113 // Helper for glGetVertexAttrib
1114 void GetVertexAttribHelper(
1115 const VertexAttrib* attrib, GLenum pname, GLint* param);
1117 // Wrapper for glCreateProgram
1118 bool CreateProgramHelper(GLuint client_id);
1120 // Wrapper for glCreateShader
1121 bool CreateShaderHelper(GLenum type, GLuint client_id);
1123 // Wrapper for glActiveTexture
1124 void DoActiveTexture(GLenum texture_unit);
1126 // Wrapper for glAttachShader
1127 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1129 // Wrapper for glBindBuffer since we need to track the current targets.
1130 void DoBindBuffer(GLenum target, GLuint buffer);
1132 // Wrapper for glBindFramebuffer since we need to track the current targets.
1133 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1135 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1136 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1138 // Wrapper for glBindTexture since we need to track the current targets.
1139 void DoBindTexture(GLenum target, GLuint texture);
1141 // Wrapper for glBindVertexArrayOES
1142 void DoBindVertexArrayOES(GLuint array);
1143 void EmulateVertexArrayState();
1145 // Wrapper for glBlitFramebufferCHROMIUM.
1146 void DoBlitFramebufferCHROMIUM(
1147 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1148 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1149 GLbitfield mask, GLenum filter);
1151 // Wrapper for glBufferSubData.
1152 void DoBufferSubData(
1153 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1155 // Wrapper for glCheckFramebufferStatus
1156 GLenum DoCheckFramebufferStatus(GLenum target);
1158 // Wrapper for glClear
1159 error::Error DoClear(GLbitfield mask);
1161 // Wrappers for various state.
1162 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1163 void DoSampleCoverage(GLclampf value, GLboolean invert);
1165 // Wrapper for glCompileShader.
1166 void DoCompileShader(GLuint shader);
1168 // Helper for DeleteSharedIdsCHROMIUM commands.
1169 void DoDeleteSharedIdsCHROMIUM(
1170 GLuint namespace_id, GLsizei n, const GLuint* ids);
1172 // Wrapper for glDetachShader
1173 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1175 // Wrapper for glDisable
1176 void DoDisable(GLenum cap);
1178 // Wrapper for glDisableVertexAttribArray.
1179 void DoDisableVertexAttribArray(GLuint index);
1181 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1183 void DoDiscardFramebufferEXT(GLenum target,
1184 GLsizei numAttachments,
1185 const GLenum* attachments);
1187 // Wrapper for glEnable
1188 void DoEnable(GLenum cap);
1190 // Wrapper for glEnableVertexAttribArray.
1191 void DoEnableVertexAttribArray(GLuint index);
1193 // Wrapper for glFinish.
1196 // Wrapper for glFlush.
1199 // Wrapper for glFramebufferRenderbufffer.
1200 void DoFramebufferRenderbuffer(
1201 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1202 GLuint renderbuffer);
1204 // Wrapper for glFramebufferTexture2D.
1205 void DoFramebufferTexture2D(
1206 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1209 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1210 void DoFramebufferTexture2DMultisample(
1211 GLenum target, GLenum attachment, GLenum textarget,
1212 GLuint texture, GLint level, GLsizei samples);
1214 // Common implementation for both DoFramebufferTexture2D wrappers.
1215 void DoFramebufferTexture2DCommon(const char* name,
1216 GLenum target, GLenum attachment, GLenum textarget,
1217 GLuint texture, GLint level, GLsizei samples);
1219 // Wrapper for glGenerateMipmap
1220 void DoGenerateMipmap(GLenum target);
1222 // Helper for GenSharedIdsCHROMIUM commands.
1223 void DoGenSharedIdsCHROMIUM(
1224 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1226 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1227 // to account for different pname values defined in different extension
1229 GLenum AdjustGetPname(GLenum pname);
1231 // Wrapper for DoGetBooleanv.
1232 void DoGetBooleanv(GLenum pname, GLboolean* params);
1234 // Wrapper for DoGetFloatv.
1235 void DoGetFloatv(GLenum pname, GLfloat* params);
1237 // Wrapper for glGetFramebufferAttachmentParameteriv.
1238 void DoGetFramebufferAttachmentParameteriv(
1239 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1241 // Wrapper for glGetIntegerv.
1242 void DoGetIntegerv(GLenum pname, GLint* params);
1244 // Gets the max value in a range in a buffer.
1245 GLuint DoGetMaxValueInBufferCHROMIUM(
1246 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1248 // Wrapper for glGetBufferParameteriv.
1249 void DoGetBufferParameteriv(
1250 GLenum target, GLenum pname, GLint* params);
1252 // Wrapper for glGetProgramiv.
1253 void DoGetProgramiv(
1254 GLuint program_id, GLenum pname, GLint* params);
1256 // Wrapper for glRenderbufferParameteriv.
1257 void DoGetRenderbufferParameteriv(
1258 GLenum target, GLenum pname, GLint* params);
1260 // Wrapper for glGetShaderiv
1261 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1263 // Wrappers for glGetVertexAttrib.
1264 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1265 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1267 // Wrappers for glIsXXX functions.
1268 bool DoIsEnabled(GLenum cap);
1269 bool DoIsBuffer(GLuint client_id);
1270 bool DoIsFramebuffer(GLuint client_id);
1271 bool DoIsProgram(GLuint client_id);
1272 bool DoIsRenderbuffer(GLuint client_id);
1273 bool DoIsShader(GLuint client_id);
1274 bool DoIsTexture(GLuint client_id);
1275 bool DoIsVertexArrayOES(GLuint client_id);
1277 // Wrapper for glLinkProgram
1278 void DoLinkProgram(GLuint program);
1280 // Helper for RegisterSharedIdsCHROMIUM.
1281 void DoRegisterSharedIdsCHROMIUM(
1282 GLuint namespace_id, GLsizei n, const GLuint* ids);
1284 // Wrapper for glRenderbufferStorage.
1285 void DoRenderbufferStorage(
1286 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1288 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1289 void DoRenderbufferStorageMultisampleCHROMIUM(
1290 GLenum target, GLsizei samples, GLenum internalformat,
1291 GLsizei width, GLsizei height);
1293 // Handler for glRenderbufferStorageMultisampleEXT
1294 // (multisampled_render_to_texture).
1295 void DoRenderbufferStorageMultisampleEXT(
1296 GLenum target, GLsizei samples, GLenum internalformat,
1297 GLsizei width, GLsizei height);
1299 // Common validation for multisample extensions.
1300 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1301 GLenum internalformat,
1305 // Verifies that the currently bound multisample renderbuffer is valid
1306 // Very slow! Only done on platforms with driver bugs that return invalid
1307 // buffers under memory pressure
1308 bool VerifyMultisampleRenderbufferIntegrity(
1309 GLuint renderbuffer, GLenum format);
1311 // Wrapper for glReleaseShaderCompiler.
1312 void DoReleaseShaderCompiler() { }
1314 // Wrappers for glTexParameter functions.
1315 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1316 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1317 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1318 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1320 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1321 // spec only these 2 functions can be used to set sampler uniforms.
1322 void DoUniform1i(GLint fake_location, GLint v0);
1323 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1324 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1325 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1326 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1328 // Wrappers for glUniformfv because some drivers don't correctly accept
1330 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1331 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1332 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1333 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1335 void DoUniformMatrix2fv(
1336 GLint fake_location, GLsizei count, GLboolean transpose,
1337 const GLfloat* value);
1338 void DoUniformMatrix3fv(
1339 GLint fake_location, GLsizei count, GLboolean transpose,
1340 const GLfloat* value);
1341 void DoUniformMatrix4fv(
1342 GLint fake_location, GLsizei count, GLboolean transpose,
1343 const GLfloat* value);
1345 bool SetVertexAttribValue(
1346 const char* function_name, GLuint index, const GLfloat* value);
1348 // Wrappers for glVertexAttrib??
1349 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1350 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1351 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1352 void DoVertexAttrib4f(
1353 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1354 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1355 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1356 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1357 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1359 // Wrapper for glViewport
1360 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1362 // Wrapper for glUseProgram
1363 void DoUseProgram(GLuint program);
1365 // Wrapper for glValidateProgram.
1366 void DoValidateProgram(GLuint program_client_id);
1368 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1369 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1370 void DoPopGroupMarkerEXT(void);
1372 // Gets the number of values that will be returned by glGetXXX. Returns
1373 // false if pname is unknown.
1374 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1376 // Checks if the current program and vertex attributes are valid for drawing.
1378 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1380 // Returns true if successful, simulated will be true if attrib0 was
1382 bool SimulateAttrib0(
1383 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1384 void RestoreStateForAttrib(GLuint attrib);
1386 // If an image is bound to texture, this will call Will/DidUseTexImage
1388 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1389 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1391 // Returns false if textures were replaced.
1392 bool PrepareTexturesForRender();
1393 void RestoreStateForTextures();
1395 // Returns true if GL_FIXED attribs were simulated.
1396 bool SimulateFixedAttribs(
1397 const char* function_name,
1398 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1399 void RestoreStateForSimulatedFixedAttribs();
1401 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1402 // cases (primcount is 0 for non-instanced).
1403 error::Error DoDrawArrays(
1404 const char* function_name,
1405 bool instanced, GLenum mode, GLint first, GLsizei count,
1407 error::Error DoDrawElements(
1408 const char* function_name,
1409 bool instanced, GLenum mode, GLsizei count, GLenum type,
1410 int32 offset, GLsizei primcount);
1412 GLenum GetBindTargetForSamplerType(GLenum type) {
1413 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1414 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1417 return GL_TEXTURE_2D;
1418 case GL_SAMPLER_CUBE:
1419 return GL_TEXTURE_CUBE_MAP;
1420 case GL_SAMPLER_EXTERNAL_OES:
1421 return GL_TEXTURE_EXTERNAL_OES;
1422 case GL_SAMPLER_2D_RECT_ARB:
1423 return GL_TEXTURE_RECTANGLE_ARB;
1430 // Gets the framebuffer info for a particular target.
1431 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1432 Framebuffer* framebuffer = NULL;
1434 case GL_FRAMEBUFFER:
1435 case GL_DRAW_FRAMEBUFFER_EXT:
1436 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1438 case GL_READ_FRAMEBUFFER_EXT:
1439 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1448 Renderbuffer* GetRenderbufferInfoForTarget(
1450 Renderbuffer* renderbuffer = NULL;
1452 case GL_RENDERBUFFER:
1453 renderbuffer = state_.bound_renderbuffer.get();
1459 return renderbuffer;
1462 // Validates the program and location for a glGetUniform call and returns
1463 // a SizeResult setup to receive the result. Returns true if glGetUniform
1464 // should be called.
1465 bool GetUniformSetup(
1466 GLuint program, GLint fake_location,
1467 uint32 shm_id, uint32 shm_offset,
1468 error::Error* error, GLint* real_location, GLuint* service_id,
1469 void** result, GLenum* result_type);
1471 virtual bool WasContextLost() OVERRIDE;
1472 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1473 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1475 #if defined(OS_MACOSX)
1476 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1479 bool ValidateCompressedTexDimensions(
1480 const char* function_name,
1481 GLint level, GLsizei width, GLsizei height, GLenum format);
1482 bool ValidateCompressedTexFuncData(
1483 const char* function_name,
1484 GLsizei width, GLsizei height, GLenum format, size_t size);
1485 bool ValidateCompressedTexSubDimensions(
1486 const char* function_name,
1487 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1488 GLsizei width, GLsizei height, GLenum format,
1491 void RenderWarning(const char* filename, int line, const std::string& msg);
1492 void PerformanceWarning(
1493 const char* filename, int line, const std::string& msg);
1495 const FeatureInfo::FeatureFlags& features() const {
1496 return feature_info_->feature_flags();
1499 const FeatureInfo::Workarounds& workarounds() const {
1500 return feature_info_->workarounds();
1503 bool ShouldDeferDraws() {
1504 return !offscreen_target_frame_buffer_.get() &&
1505 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1506 surface_->DeferDraws();
1509 bool ShouldDeferReads() {
1510 return !offscreen_target_frame_buffer_.get() &&
1511 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1512 surface_->DeferDraws();
1515 error::Error WillAccessBoundFramebufferForDraw() {
1516 if (ShouldDeferDraws())
1517 return error::kDeferCommandUntilLater;
1518 if (!offscreen_target_frame_buffer_.get() &&
1519 !framebuffer_state_.bound_draw_framebuffer.get() &&
1520 !surface_->SetBackbufferAllocation(true))
1521 return error::kLostContext;
1522 return error::kNoError;
1525 error::Error WillAccessBoundFramebufferForRead() {
1526 if (ShouldDeferReads())
1527 return error::kDeferCommandUntilLater;
1528 if (!offscreen_target_frame_buffer_.get() &&
1529 !framebuffer_state_.bound_read_framebuffer.get() &&
1530 !surface_->SetBackbufferAllocation(true))
1531 return error::kLostContext;
1532 return error::kNoError;
1535 void ProcessPendingReadPixels();
1536 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1538 // Generate a member function prototype for each command in an automated and
1540 #define GLES2_CMD_OP(name) \
1541 Error Handle ## name( \
1542 uint32 immediate_data_size, \
1543 const cmds::name& args); \
1545 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1549 // The GL context this decoder renders to on behalf of the client.
1550 scoped_refptr<gfx::GLSurface> surface_;
1551 scoped_refptr<gfx::GLContext> context_;
1553 // The ContextGroup for this decoder uses to track resources.
1554 scoped_refptr<ContextGroup> group_;
1556 DebugMarkerManager debug_marker_manager_;
1559 // All the state for this context.
1560 ContextState state_;
1562 // Current width and height of the offscreen frame buffer.
1563 gfx::Size offscreen_size_;
1565 // Util to help with GL.
1568 // unpack flip y as last set by glPixelStorei
1569 bool unpack_flip_y_;
1571 // unpack (un)premultiply alpha as last set by glPixelStorei
1572 bool unpack_premultiply_alpha_;
1573 bool unpack_unpremultiply_alpha_;
1575 // Default vertex attribs manager, used when no VAOs are bound.
1576 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
1578 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1579 GLuint attrib_0_buffer_id_;
1581 // The value currently in attrib_0.
1582 Vec4 attrib_0_value_;
1584 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1585 bool attrib_0_buffer_matches_value_;
1587 // The size of attrib 0.
1588 GLsizei attrib_0_size_;
1590 // The buffer used to simulate GL_FIXED attribs.
1591 GLuint fixed_attrib_buffer_id_;
1593 // The size of fiixed attrib buffer.
1594 GLsizei fixed_attrib_buffer_size_;
1596 // The offscreen frame buffer that the client renders to. With EGL, the
1597 // depth and stencil buffers are separate. With regular GL there is a single
1598 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1599 // offscreen_target_stencil_render_buffer_ is unused.
1600 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1601 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1602 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1603 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1604 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1605 GLenum offscreen_target_color_format_;
1606 GLenum offscreen_target_depth_format_;
1607 GLenum offscreen_target_stencil_format_;
1608 GLsizei offscreen_target_samples_;
1609 GLboolean offscreen_target_buffer_preserved_;
1611 // The copy that is saved when SwapBuffers is called.
1612 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1613 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1614 scoped_refptr<TextureRef>
1615 offscreen_saved_color_texture_info_;
1617 // The copy that is used as the destination for multi-sample resolves.
1618 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1619 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1620 GLenum offscreen_saved_color_format_;
1622 scoped_ptr<QueryManager> query_manager_;
1624 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1626 base::Callback<void(gfx::Size, float)> resize_callback_;
1628 WaitSyncPointCallback wait_sync_point_callback_;
1630 ShaderCacheCallback shader_cache_callback_;
1632 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1634 // The format of the back buffer_
1635 GLenum back_buffer_color_format_;
1636 bool back_buffer_has_depth_;
1637 bool back_buffer_has_stencil_;
1639 // Backbuffer attachments that are currently undefined.
1640 uint32 backbuffer_needs_clear_bits_;
1642 // The current decoder error.
1643 error::Error current_decoder_error_;
1645 bool use_shader_translator_;
1646 scoped_refptr<ShaderTranslator> vertex_translator_;
1647 scoped_refptr<ShaderTranslator> fragment_translator_;
1649 DisallowedFeatures disallowed_features_;
1651 // Cached from ContextGroup
1652 const Validators* validators_;
1653 scoped_refptr<FeatureInfo> feature_info_;
1657 bool has_robustness_extension_;
1658 GLenum reset_status_;
1659 bool reset_by_robustness_extension_;
1661 // These flags are used to override the state of the shared feature_info_
1662 // member. Because the same FeatureInfo instance may be shared among many
1663 // contexts, the assumptions on the availablity of extensions in WebGL
1664 // contexts may be broken. These flags override the shared state to preserve
1666 bool force_webgl_glsl_validation_;
1667 bool derivatives_explicitly_enabled_;
1668 bool frag_depth_explicitly_enabled_;
1669 bool draw_buffers_explicitly_enabled_;
1671 bool compile_shader_always_succeeds_;
1674 bool service_logging_;
1676 #if defined(OS_MACOSX)
1677 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1678 TextureToIOSurfaceMap texture_to_io_surface_map_;
1681 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1683 // Cached values of the currently assigned viewport dimensions.
1684 GLsizei viewport_max_width_;
1685 GLsizei viewport_max_height_;
1687 // Command buffer stats.
1688 base::TimeDelta total_processing_commands_time_;
1690 // States related to each manager.
1691 DecoderTextureState texture_state_;
1692 DecoderFramebufferState framebuffer_state_;
1694 scoped_ptr<GPUTracer> gpu_tracer_;
1695 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1696 int gpu_trace_level_;
1697 bool gpu_trace_commands_;
1699 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1701 // Used to validate multisample renderbuffers if needed
1702 GLuint validation_texture_;
1703 GLuint validation_fbo_multisample_;
1704 GLuint validation_fbo_;
1706 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1709 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1710 const char* function_name, ErrorState* error_state)
1711 : function_name_(function_name),
1712 error_state_(error_state) {
1713 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1716 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1717 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1720 static void RestoreCurrentTexture2DBindings(ContextState* state) {
1721 TextureUnit& info = state->texture_units[0];
1723 if (info.bound_texture_2d.get()) {
1724 last_id = info.bound_texture_2d->service_id();
1729 glBindTexture(GL_TEXTURE_2D, last_id);
1730 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1733 ScopedTexture2DBinder::ScopedTexture2DBinder(ContextState* state,
1736 ScopedGLErrorSuppressor suppressor(
1737 "ScopedTexture2DBinder::ctor", state_->GetErrorState());
1739 // TODO(apatrick): Check if there are any other states that need to be reset
1740 // before binding a new texture.
1741 glActiveTexture(GL_TEXTURE0);
1742 glBindTexture(GL_TEXTURE_2D, id);
1745 ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1746 ScopedGLErrorSuppressor suppressor(
1747 "ScopedTexture2DBinder::dtor", state_->GetErrorState());
1748 RestoreCurrentTexture2DBindings(state_);
1751 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1754 ScopedGLErrorSuppressor suppressor(
1755 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1756 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1759 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1760 ScopedGLErrorSuppressor suppressor(
1761 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1762 state_->RestoreRenderbufferBindings();
1765 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1767 : decoder_(decoder) {
1768 ScopedGLErrorSuppressor suppressor(
1769 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1770 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1771 decoder->OnFboChanged();
1774 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1775 ScopedGLErrorSuppressor suppressor(
1776 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1777 decoder_->RestoreCurrentFramebufferBindings();
1780 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1781 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1782 : decoder_(decoder) {
1783 resolve_and_bind_ = (
1784 decoder_->offscreen_target_frame_buffer_.get() &&
1785 decoder_->IsOffscreenBufferMultisampled() &&
1786 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1787 enforce_internal_framebuffer));
1788 if (!resolve_and_bind_)
1791 ScopedGLErrorSuppressor suppressor(
1792 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1793 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1794 decoder_->offscreen_target_frame_buffer_->id());
1797 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1798 decoder_->offscreen_resolved_frame_buffer_.reset(
1799 new BackFramebuffer(decoder_));
1800 decoder_->offscreen_resolved_frame_buffer_->Create();
1801 decoder_->offscreen_resolved_color_texture_.reset(
1802 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1803 decoder_->offscreen_resolved_color_texture_->Create();
1805 DCHECK(decoder_->offscreen_saved_color_format_);
1806 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1807 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1809 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1810 decoder_->offscreen_resolved_color_texture_.get());
1811 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1812 GL_FRAMEBUFFER_COMPLETE) {
1813 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1814 << "because offscreen resolved FBO was incomplete.";
1818 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1820 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1822 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1823 const int width = decoder_->offscreen_size_.width();
1824 const int height = decoder_->offscreen_size_.height();
1825 glDisable(GL_SCISSOR_TEST);
1826 decoder->BlitFramebufferHelper(0,
1834 GL_COLOR_BUFFER_BIT,
1836 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1839 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1840 if (!resolve_and_bind_)
1843 ScopedGLErrorSuppressor suppressor(
1844 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1845 decoder_->RestoreCurrentFramebufferBindings();
1846 if (decoder_->state_.enable_flags.scissor_test) {
1847 glEnable(GL_SCISSOR_TEST);
1851 BackTexture::BackTexture(
1852 MemoryTracker* memory_tracker,
1853 ContextState* state)
1854 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1856 bytes_allocated_(0),
1860 BackTexture::~BackTexture() {
1861 // This does not destroy the render texture because that would require that
1862 // the associated GL context was current. Just check that it was explicitly
1867 void BackTexture::Create() {
1868 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1869 state_->GetErrorState());
1871 glGenTextures(1, &id_);
1872 ScopedTexture2DBinder binder(state_, id_);
1873 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1874 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1875 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1876 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1878 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1879 // never called on an offscreen context, no data will ever be uploaded to the
1880 // saved offscreen color texture (it is deferred until to when SwapBuffers
1881 // is called). My idea is that some nvidia drivers might have a bug where
1882 // deleting a texture that has never been populated might cause a
1885 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1887 bytes_allocated_ = 16u * 16u * 4u;
1888 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1891 bool BackTexture::AllocateStorage(
1892 const gfx::Size& size, GLenum format, bool zero) {
1894 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
1895 state_->GetErrorState());
1896 ScopedTexture2DBinder binder(state_, id_);
1897 uint32 image_size = 0;
1898 GLES2Util::ComputeImageDataSizes(
1899 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1902 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1906 scoped_ptr<char[]> zero_data;
1908 zero_data.reset(new char[image_size]);
1909 memset(zero_data.get(), 0, image_size);
1912 glTexImage2D(GL_TEXTURE_2D,
1924 bool success = glGetError() == GL_NO_ERROR;
1926 memory_tracker_.TrackMemFree(bytes_allocated_);
1927 bytes_allocated_ = image_size;
1928 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1933 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
1935 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
1936 state_->GetErrorState());
1937 ScopedTexture2DBinder binder(state_, id_);
1938 glCopyTexImage2D(GL_TEXTURE_2D,
1947 void BackTexture::Destroy() {
1949 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
1950 state_->GetErrorState());
1951 glDeleteTextures(1, &id_);
1954 memory_tracker_.TrackMemFree(bytes_allocated_);
1955 bytes_allocated_ = 0;
1958 void BackTexture::Invalidate() {
1962 BackRenderbuffer::BackRenderbuffer(
1963 RenderbufferManager* renderbuffer_manager,
1964 MemoryTracker* memory_tracker,
1965 ContextState* state)
1966 : renderbuffer_manager_(renderbuffer_manager),
1967 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1969 bytes_allocated_(0),
1973 BackRenderbuffer::~BackRenderbuffer() {
1974 // This does not destroy the render buffer because that would require that
1975 // the associated GL context was current. Just check that it was explicitly
1980 void BackRenderbuffer::Create() {
1981 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
1982 state_->GetErrorState());
1984 glGenRenderbuffersEXT(1, &id_);
1987 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
1988 const gfx::Size& size,
1991 ScopedGLErrorSuppressor suppressor(
1992 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
1993 ScopedRenderBufferBinder binder(state_, id_);
1995 uint32 estimated_size = 0;
1996 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
1997 size.width(), size.height(), samples, format, &estimated_size)) {
2001 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2006 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2011 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2018 bool success = glGetError() == GL_NO_ERROR;
2020 // Mark the previously allocated bytes as free.
2021 memory_tracker_.TrackMemFree(bytes_allocated_);
2022 bytes_allocated_ = estimated_size;
2023 // Track the newly allocated bytes.
2024 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2029 void BackRenderbuffer::Destroy() {
2031 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2032 state_->GetErrorState());
2033 glDeleteRenderbuffersEXT(1, &id_);
2036 memory_tracker_.TrackMemFree(bytes_allocated_);
2037 bytes_allocated_ = 0;
2040 void BackRenderbuffer::Invalidate() {
2044 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2045 : decoder_(decoder),
2049 BackFramebuffer::~BackFramebuffer() {
2050 // This does not destroy the frame buffer because that would require that
2051 // the associated GL context was current. Just check that it was explicitly
2056 void BackFramebuffer::Create() {
2057 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2058 decoder_->GetErrorState());
2060 glGenFramebuffersEXT(1, &id_);
2063 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2065 ScopedGLErrorSuppressor suppressor(
2066 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2067 ScopedFrameBufferBinder binder(decoder_, id_);
2068 GLuint attach_id = texture ? texture->id() : 0;
2069 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2070 GL_COLOR_ATTACHMENT0,
2076 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2077 BackRenderbuffer* render_buffer) {
2079 ScopedGLErrorSuppressor suppressor(
2080 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2081 ScopedFrameBufferBinder binder(decoder_, id_);
2082 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2083 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2089 void BackFramebuffer::Destroy() {
2091 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2092 decoder_->GetErrorState());
2093 glDeleteFramebuffersEXT(1, &id_);
2098 void BackFramebuffer::Invalidate() {
2102 GLenum BackFramebuffer::CheckStatus() {
2104 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2105 decoder_->GetErrorState());
2106 ScopedFrameBufferBinder binder(decoder_, id_);
2107 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2110 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2111 return new GLES2DecoderImpl(group);
2114 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2117 logger_(&debug_marker_manager_),
2118 state_(group_->feature_info(), &logger_),
2119 unpack_flip_y_(false),
2120 unpack_premultiply_alpha_(false),
2121 unpack_unpremultiply_alpha_(false),
2122 attrib_0_buffer_id_(0),
2123 attrib_0_buffer_matches_value_(true),
2125 fixed_attrib_buffer_id_(0),
2126 fixed_attrib_buffer_size_(0),
2127 offscreen_target_color_format_(0),
2128 offscreen_target_depth_format_(0),
2129 offscreen_target_stencil_format_(0),
2130 offscreen_target_samples_(0),
2131 offscreen_target_buffer_preserved_(true),
2132 offscreen_saved_color_format_(0),
2133 back_buffer_color_format_(0),
2134 back_buffer_has_depth_(false),
2135 back_buffer_has_stencil_(false),
2136 backbuffer_needs_clear_bits_(0),
2137 current_decoder_error_(error::kNoError),
2138 use_shader_translator_(true),
2139 validators_(group_->feature_info()->validators()),
2140 feature_info_(group_->feature_info()),
2142 has_robustness_extension_(false),
2143 reset_status_(GL_NO_ERROR),
2144 reset_by_robustness_extension_(false),
2145 force_webgl_glsl_validation_(false),
2146 derivatives_explicitly_enabled_(false),
2147 frag_depth_explicitly_enabled_(false),
2148 draw_buffers_explicitly_enabled_(false),
2149 compile_shader_always_succeeds_(false),
2150 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2151 switches::kEnableGPUServiceLoggingGPU)),
2152 viewport_max_width_(0),
2153 viewport_max_height_(0),
2154 texture_state_(group_->feature_info()
2156 .texsubimage2d_faster_than_teximage2d),
2157 validation_texture_(0),
2158 validation_fbo_multisample_(0),
2159 validation_fbo_(0) {
2162 attrib_0_value_.v[0] = 0.0f;
2163 attrib_0_value_.v[1] = 0.0f;
2164 attrib_0_value_.v[2] = 0.0f;
2165 attrib_0_value_.v[3] = 1.0f;
2167 // The shader translator is used for WebGL even when running on EGL
2168 // because additional restrictions are needed (like only enabling
2169 // GL_OES_standard_derivatives on demand). It is used for the unit
2170 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2171 // the empty string to CompileShader and this is not a valid shader.
2172 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2173 CommandLine::ForCurrentProcess()->HasSwitch(
2174 switches::kDisableGLSLTranslator)) {
2175 use_shader_translator_ = false;
2179 GLES2DecoderImpl::~GLES2DecoderImpl() {
2182 bool GLES2DecoderImpl::Initialize(
2183 const scoped_refptr<gfx::GLSurface>& surface,
2184 const scoped_refptr<gfx::GLContext>& context,
2186 const gfx::Size& size,
2187 const DisallowedFeatures& disallowed_features,
2188 const std::vector<int32>& attribs) {
2189 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2190 DCHECK(context->IsCurrent(surface.get()));
2191 DCHECK(!context_.get());
2194 gpu_tracer_ = GPUTracer::Create(this);
2195 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2196 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2197 gpu_trace_level_ = 2;
2198 gpu_trace_commands_ = false;
2200 if (CommandLine::ForCurrentProcess()->HasSwitch(
2201 switches::kEnableGPUDebugging)) {
2205 if (CommandLine::ForCurrentProcess()->HasSwitch(
2206 switches::kEnableGPUCommandLogging)) {
2207 set_log_commands(true);
2210 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2211 switches::kCompileShaderAlwaysSucceeds);
2214 // Take ownership of the context and surface. The surface can be replaced with
2219 ContextCreationAttribHelper attrib_parser;
2220 if (!attrib_parser.Parse(attribs))
2223 // If the failIfMajorPerformanceCaveat context creation attribute was true
2224 // and we are using a software renderer, fail.
2225 if (attrib_parser.fail_if_major_perf_caveat_ &&
2226 feature_info_->feature_flags().is_swiftshader) {
2227 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2232 if (!group_->Initialize(this, disallowed_features)) {
2233 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2234 << "failed to initialize.";
2235 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2241 disallowed_features_ = disallowed_features;
2243 state_.attrib_values.resize(group_->max_vertex_attribs());
2244 default_vertex_attrib_manager_ = new VertexAttribManager();
2245 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2247 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2248 DoBindVertexArrayOES(0);
2250 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2251 vertex_array_manager_.reset(new VertexArrayManager());
2253 util_.set_num_compressed_texture_formats(
2254 validators_->compressed_texture_format.GetValues().size());
2256 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2257 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2258 // OpenGL ES 2.0 does not have this issue.
2259 glEnableVertexAttribArray(0);
2261 glGenBuffersARB(1, &attrib_0_buffer_id_);
2262 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2263 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2264 glBindBuffer(GL_ARRAY_BUFFER, 0);
2265 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2267 state_.texture_units.resize(group_->max_texture_units());
2268 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2269 glActiveTexture(GL_TEXTURE0 + tt);
2270 // We want the last bind to be 2D.
2272 if (features().oes_egl_image_external) {
2273 ref = texture_manager()->GetDefaultTextureInfo(
2274 GL_TEXTURE_EXTERNAL_OES);
2275 state_.texture_units[tt].bound_texture_external_oes = ref;
2276 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
2278 if (features().arb_texture_rectangle) {
2279 ref = texture_manager()->GetDefaultTextureInfo(
2280 GL_TEXTURE_RECTANGLE_ARB);
2281 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2282 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
2284 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2285 state_.texture_units[tt].bound_texture_cube_map = ref;
2286 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2287 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2288 state_.texture_units[tt].bound_texture_2d = ref;
2289 glBindTexture(GL_TEXTURE_2D, ref->service_id());
2291 glActiveTexture(GL_TEXTURE0);
2295 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2296 features().chromium_framebuffer_multisample) {
2297 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2298 // max_sample_count must be initialized to a sane value. If
2299 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2300 GLint max_sample_count = 1;
2301 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2302 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2305 offscreen_target_samples_ = 1;
2307 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2309 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2310 const bool rgb8_supported =
2311 context_->HasExtension("GL_OES_rgb8_rgba8");
2312 // The only available default render buffer formats in GLES2 have very
2313 // little precision. Don't enable multisampling unless 8-bit render
2314 // buffer formats are available--instead fall back to 8-bit textures.
2315 if (rgb8_supported && offscreen_target_samples_ > 1) {
2316 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2319 offscreen_target_samples_ = 1;
2320 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2324 // ANGLE only supports packed depth/stencil formats, so use it if it is
2326 const bool depth24_stencil8_supported =
2327 feature_info_->feature_flags().packed_depth24_stencil8;
2328 VLOG(1) << "GL_OES_packed_depth_stencil "
2329 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2330 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2331 depth24_stencil8_supported) {
2332 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2333 offscreen_target_stencil_format_ = 0;
2335 // It may be the case that this depth/stencil combination is not
2336 // supported, but this will be checked later by CheckFramebufferStatus.
2337 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2338 GL_DEPTH_COMPONENT16 : 0;
2339 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2340 GL_STENCIL_INDEX8 : 0;
2343 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2346 // If depth is requested at all, use the packed depth stencil format if
2347 // it's available, as some desktop GL drivers don't support any non-packed
2348 // formats for depth attachments.
2349 const bool depth24_stencil8_supported =
2350 feature_info_->feature_flags().packed_depth24_stencil8;
2351 VLOG(1) << "GL_EXT_packed_depth_stencil "
2352 << (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 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2360 GL_DEPTH_COMPONENT : 0;
2361 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2362 GL_STENCIL_INDEX : 0;
2366 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2369 // Create the target frame buffer. This is the one that the client renders
2371 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2372 offscreen_target_frame_buffer_->Create();
2373 // Due to GLES2 format limitations, either the color texture (for
2374 // non-multisampling) or the color render buffer (for multisampling) will be
2375 // attached to the offscreen frame buffer. The render buffer has more
2376 // limited formats available to it, but the texture can't do multisampling.
2377 if (IsOffscreenBufferMultisampled()) {
2378 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2379 renderbuffer_manager(), memory_tracker(), &state_));
2380 offscreen_target_color_render_buffer_->Create();
2382 offscreen_target_color_texture_.reset(new BackTexture(
2383 memory_tracker(), &state_));
2384 offscreen_target_color_texture_->Create();
2386 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2387 renderbuffer_manager(), memory_tracker(), &state_));
2388 offscreen_target_depth_render_buffer_->Create();
2389 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2390 renderbuffer_manager(), memory_tracker(), &state_));
2391 offscreen_target_stencil_render_buffer_->Create();
2393 // Create the saved offscreen texture. The target frame buffer is copied
2394 // here when SwapBuffers is called.
2395 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2396 offscreen_saved_frame_buffer_->Create();
2398 offscreen_saved_color_texture_.reset(new BackTexture(
2399 memory_tracker(), &state_));
2400 offscreen_saved_color_texture_->Create();
2402 // Allocate the render buffers at their initial size and check the status
2403 // of the frame buffers is okay.
2404 if (!ResizeOffscreenFrameBuffer(size)) {
2405 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2410 // Allocate the offscreen saved color texture.
2411 DCHECK(offscreen_saved_color_format_);
2412 offscreen_saved_color_texture_->AllocateStorage(
2413 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2415 offscreen_saved_frame_buffer_->AttachRenderTexture(
2416 offscreen_saved_color_texture_.get());
2417 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2418 GL_FRAMEBUFFER_COMPLETE) {
2419 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2424 // Bind to the new default frame buffer (the offscreen target frame buffer).
2425 // This should now be associated with ID zero.
2426 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2428 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2429 // These are NOT if the back buffer has these proprorties. They are
2430 // if we want the command buffer to enforce them regardless of what
2431 // the real backbuffer is assuming the real back buffer gives us more than
2432 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2433 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2434 // can't do anything about that.
2437 glGetIntegerv(GL_ALPHA_BITS, &v);
2438 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2439 // user requested RGB then RGB. If the user did not specify a preference
2440 // than use whatever we were given. Same for DEPTH and STENCIL.
2441 back_buffer_color_format_ =
2442 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2443 glGetIntegerv(GL_DEPTH_BITS, &v);
2444 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2445 glGetIntegerv(GL_STENCIL_BITS, &v);
2446 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2449 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2450 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2451 // isn't well documented; it was discovered in the Khronos OpenGL ES
2452 // mailing list archives. It also implicitly enables the desktop GL
2453 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2454 // variable in fragment shaders.
2455 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2456 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2457 glEnable(GL_POINT_SPRITE);
2460 has_robustness_extension_ =
2461 context->HasExtension("GL_ARB_robustness") ||
2462 context->HasExtension("GL_EXT_robustness");
2464 if (!InitializeShaderTranslator()) {
2468 state_.viewport_width = size.width();
2469 state_.viewport_height = size.height();
2471 GLint viewport_params[4] = { 0 };
2472 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2473 viewport_max_width_ = viewport_params[0];
2474 viewport_max_height_ = viewport_params[1];
2476 state_.scissor_width = state_.viewport_width;
2477 state_.scissor_height = state_.viewport_height;
2479 // Set all the default state because some GL drivers get it wrong.
2480 state_.InitCapabilities();
2482 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2484 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2485 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2486 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2487 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2489 bool call_gl_clear = true;
2490 #if defined(OS_ANDROID)
2491 // Temporary workaround for Android WebView because this clear ignores the
2492 // clip and corrupts that external UI of the App. Not calling glClear is ok
2493 // because the system already clears the buffer before each draw. Proper
2494 // fix might be setting the scissor clip properly before initialize. See
2495 // crbug.com/259023 for details.
2496 call_gl_clear = surface_->GetHandle();
2498 if (call_gl_clear) {
2499 // Clear the backbuffer.
2500 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2503 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2504 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2507 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2508 context_->SetUnbindFboOnMakeCurrent();
2511 if (feature_info_->workarounds().release_image_after_use) {
2512 image_manager()->SetReleaseAfterUse();
2515 // Only compositor contexts are known to use only the subset of GL
2516 // that can be safely migrated between the iGPU and the dGPU. Mark
2517 // those contexts as safe to forcibly transition between the GPUs.
2518 // http://crbug.com/180876, http://crbug.com/227228
2520 context_->SetSafeToForceGpuSwitch();
2522 async_pixel_transfer_manager_.reset(
2523 AsyncPixelTransferManager::Create(context.get()));
2524 async_pixel_transfer_manager_->Initialize(texture_manager());
2526 framebuffer_manager()->AddObserver(this);
2531 Capabilities GLES2DecoderImpl::GetCapabilities() {
2532 DCHECK(initialized());
2536 caps.fast_npot_mo8_textures =
2537 feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
2538 caps.egl_image_external =
2539 feature_info_->feature_flags().oes_egl_image_external;
2540 caps.texture_format_bgra8888 =
2541 feature_info_->feature_flags().ext_texture_format_bgra8888;
2542 caps.texture_format_etc1 =
2543 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2544 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2545 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2546 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2547 caps.discard_framebuffer =
2548 feature_info_->feature_flags().ext_discard_framebuffer;
2550 #if defined(OS_MACOSX)
2551 // This is unconditionally true on mac, no need to test for it at runtime.
2552 caps.iosurface = true;
2555 caps.post_sub_buffer = surface_->HasExtension("GL_CHROMIUM_post_sub_buffer");
2560 void GLES2DecoderImpl::UpdateCapabilities() {
2561 util_.set_num_compressed_texture_formats(
2562 validators_->compressed_texture_format.GetValues().size());
2563 util_.set_num_shader_binary_formats(
2564 validators_->shader_binary_format.GetValues().size());
2567 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2568 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2570 if (!use_shader_translator_) {
2573 ShBuiltInResources resources;
2574 ShInitBuiltInResources(&resources);
2575 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2576 resources.MaxVertexUniformVectors =
2577 group_->max_vertex_uniform_vectors();
2578 resources.MaxVaryingVectors = group_->max_varying_vectors();
2579 resources.MaxVertexTextureImageUnits =
2580 group_->max_vertex_texture_image_units();
2581 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2582 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2583 resources.MaxFragmentUniformVectors =
2584 group_->max_fragment_uniform_vectors();
2585 resources.MaxDrawBuffers = group_->max_draw_buffers();
2586 resources.MaxExpressionComplexity = 256;
2587 resources.MaxCallStackDepth = 256;
2589 #if (ANGLE_SH_VERSION >= 110)
2590 GLint range[2] = { 0, 0 };
2591 GLint precision = 0;
2592 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2594 resources.FragmentPrecisionHigh =
2595 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2598 if (force_webgl_glsl_validation_) {
2599 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2600 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2601 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2602 if (!draw_buffers_explicitly_enabled_)
2603 resources.MaxDrawBuffers = 1;
2605 resources.OES_standard_derivatives =
2606 features().oes_standard_derivatives ? 1 : 0;
2607 resources.ARB_texture_rectangle =
2608 features().arb_texture_rectangle ? 1 : 0;
2609 resources.OES_EGL_image_external =
2610 features().oes_egl_image_external ? 1 : 0;
2611 resources.EXT_draw_buffers =
2612 features().ext_draw_buffers ? 1 : 0;
2613 resources.EXT_frag_depth =
2614 features().ext_frag_depth ? 1 : 0;
2617 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2619 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2620 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2621 resources.HashFunction = &CityHashForAngle;
2623 resources.HashFunction = &CityHash64;
2626 resources.HashFunction = NULL;
2627 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2628 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2629 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2630 int driver_bug_workarounds = 0;
2631 if (workarounds().needs_glsl_built_in_function_emulation)
2632 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2633 if (workarounds().init_gl_position_in_vertex_shader)
2634 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2635 if (workarounds().unfold_short_circuit_as_ternary_operation)
2636 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2638 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2639 vertex_translator_ = cache->GetTranslator(
2640 SH_VERTEX_SHADER, shader_spec, &resources,
2641 implementation_type,
2642 static_cast<ShCompileOptions>(driver_bug_workarounds));
2643 if (!vertex_translator_.get()) {
2644 LOG(ERROR) << "Could not initialize vertex shader translator.";
2649 fragment_translator_ = cache->GetTranslator(
2650 SH_FRAGMENT_SHADER, shader_spec, &resources,
2651 implementation_type,
2652 static_cast<ShCompileOptions>(driver_bug_workarounds));
2653 if (!fragment_translator_.get()) {
2654 LOG(ERROR) << "Could not initialize fragment shader translator.";
2661 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2662 for (GLsizei ii = 0; ii < n; ++ii) {
2663 if (GetBuffer(client_ids[ii])) {
2667 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2668 glGenBuffersARB(n, service_ids.get());
2669 for (GLsizei ii = 0; ii < n; ++ii) {
2670 CreateBuffer(client_ids[ii], service_ids[ii]);
2675 bool GLES2DecoderImpl::GenFramebuffersHelper(
2676 GLsizei n, const GLuint* client_ids) {
2677 for (GLsizei ii = 0; ii < n; ++ii) {
2678 if (GetFramebuffer(client_ids[ii])) {
2682 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2683 glGenFramebuffersEXT(n, service_ids.get());
2684 for (GLsizei ii = 0; ii < n; ++ii) {
2685 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2690 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2691 GLsizei n, const GLuint* client_ids) {
2692 for (GLsizei ii = 0; ii < n; ++ii) {
2693 if (GetRenderbuffer(client_ids[ii])) {
2697 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2698 glGenRenderbuffersEXT(n, service_ids.get());
2699 for (GLsizei ii = 0; ii < n; ++ii) {
2700 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2705 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2706 for (GLsizei ii = 0; ii < n; ++ii) {
2707 if (GetTexture(client_ids[ii])) {
2711 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2712 glGenTextures(n, service_ids.get());
2713 for (GLsizei ii = 0; ii < n; ++ii) {
2714 CreateTexture(client_ids[ii], service_ids[ii]);
2719 void GLES2DecoderImpl::DeleteBuffersHelper(
2720 GLsizei n, const GLuint* client_ids) {
2721 for (GLsizei ii = 0; ii < n; ++ii) {
2722 Buffer* buffer = GetBuffer(client_ids[ii]);
2723 if (buffer && !buffer->IsDeleted()) {
2724 state_.vertex_attrib_manager->Unbind(buffer);
2725 if (state_.bound_array_buffer.get() == buffer) {
2726 state_.bound_array_buffer = NULL;
2728 RemoveBuffer(client_ids[ii]);
2733 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2734 GLsizei n, const GLuint* client_ids) {
2735 bool supports_separate_framebuffer_binds =
2736 features().chromium_framebuffer_multisample;
2738 for (GLsizei ii = 0; ii < n; ++ii) {
2739 Framebuffer* framebuffer =
2740 GetFramebuffer(client_ids[ii]);
2741 if (framebuffer && !framebuffer->IsDeleted()) {
2742 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2743 framebuffer_state_.bound_draw_framebuffer = NULL;
2744 framebuffer_state_.clear_state_dirty = true;
2745 GLenum target = supports_separate_framebuffer_binds ?
2746 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2747 glBindFramebufferEXT(target, GetBackbufferServiceId());
2749 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2750 framebuffer_state_.bound_read_framebuffer = NULL;
2751 GLenum target = supports_separate_framebuffer_binds ?
2752 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2753 glBindFramebufferEXT(target, GetBackbufferServiceId());
2756 RemoveFramebuffer(client_ids[ii]);
2761 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2762 GLsizei n, const GLuint* client_ids) {
2763 bool supports_separate_framebuffer_binds =
2764 features().chromium_framebuffer_multisample;
2765 for (GLsizei ii = 0; ii < n; ++ii) {
2766 Renderbuffer* renderbuffer =
2767 GetRenderbuffer(client_ids[ii]);
2768 if (renderbuffer && !renderbuffer->IsDeleted()) {
2769 if (state_.bound_renderbuffer.get() == renderbuffer) {
2770 state_.bound_renderbuffer = NULL;
2772 // Unbind from current framebuffers.
2773 if (supports_separate_framebuffer_binds) {
2774 if (framebuffer_state_.bound_read_framebuffer.get()) {
2775 framebuffer_state_.bound_read_framebuffer
2776 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2778 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2779 framebuffer_state_.bound_draw_framebuffer
2780 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2783 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2784 framebuffer_state_.bound_draw_framebuffer
2785 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2788 framebuffer_state_.clear_state_dirty = true;
2789 RemoveRenderbuffer(client_ids[ii]);
2794 void GLES2DecoderImpl::DeleteTexturesHelper(
2795 GLsizei n, const GLuint* client_ids) {
2796 bool supports_separate_framebuffer_binds =
2797 features().chromium_framebuffer_multisample;
2798 for (GLsizei ii = 0; ii < n; ++ii) {
2799 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2801 Texture* texture = texture_ref->texture();
2802 if (texture->IsAttachedToFramebuffer()) {
2803 framebuffer_state_.clear_state_dirty = true;
2805 // Unbind texture_ref from texture_ref units.
2806 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2807 state_.texture_units[jj].Unbind(texture_ref);
2809 // Unbind from current framebuffers.
2810 if (supports_separate_framebuffer_binds) {
2811 if (framebuffer_state_.bound_read_framebuffer.get()) {
2812 framebuffer_state_.bound_read_framebuffer
2813 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2815 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2816 framebuffer_state_.bound_draw_framebuffer
2817 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2820 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2821 framebuffer_state_.bound_draw_framebuffer
2822 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2825 #if defined(OS_MACOSX)
2826 GLuint service_id = texture->service_id();
2827 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2828 ReleaseIOSurfaceForTexture(service_id);
2831 RemoveTexture(client_ids[ii]);
2836 // } // anonymous namespace
2838 bool GLES2DecoderImpl::MakeCurrent() {
2839 if (!context_.get())
2842 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
2843 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2845 // Some D3D drivers cannot recover from device lost in the GPU process
2846 // sandbox. Allow a new GPU process to launch.
2847 if (workarounds().exit_on_context_lost) {
2848 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2849 << " a D3D device in the Chrome GPU process sandbox.";
2851 base::win::SetShouldCrashOnProcessDetach(false);
2859 ProcessFinishedAsyncTransfers();
2861 // Rebind the FBO if it was unbound by the context.
2862 if (workarounds().unbind_fbo_on_context_switch)
2863 RestoreFramebufferBindings();
2865 framebuffer_state_.clear_state_dirty = true;
2870 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
2871 ProcessPendingReadPixels();
2872 if (engine() && query_manager_.get())
2873 query_manager_->ProcessPendingTransferQueries();
2875 // TODO(epenner): Is there a better place to do this?
2876 // This needs to occur before we execute any batch of commands
2877 // from the client, as the client may have recieved an async
2878 // completion while issuing those commands.
2879 // "DidFlushStart" would be ideal if we had such a callback.
2880 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
2883 static void RebindCurrentFramebuffer(
2885 Framebuffer* framebuffer,
2886 GLuint back_buffer_service_id) {
2887 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
2889 if (framebuffer_id == 0) {
2890 framebuffer_id = back_buffer_service_id;
2893 glBindFramebufferEXT(target, framebuffer_id);
2896 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
2897 framebuffer_state_.clear_state_dirty = true;
2899 if (!features().chromium_framebuffer_multisample) {
2900 RebindCurrentFramebuffer(
2902 framebuffer_state_.bound_draw_framebuffer.get(),
2903 GetBackbufferServiceId());
2905 RebindCurrentFramebuffer(
2906 GL_READ_FRAMEBUFFER_EXT,
2907 framebuffer_state_.bound_read_framebuffer.get(),
2908 GetBackbufferServiceId());
2909 RebindCurrentFramebuffer(
2910 GL_DRAW_FRAMEBUFFER_EXT,
2911 framebuffer_state_.bound_draw_framebuffer.get(),
2912 GetBackbufferServiceId());
2917 bool GLES2DecoderImpl::CheckFramebufferValid(
2918 Framebuffer* framebuffer,
2919 GLenum target, const char* func_name) {
2921 if (backbuffer_needs_clear_bits_) {
2922 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2923 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2924 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2929 glDisable(GL_SCISSOR_TEST);
2930 glClear(backbuffer_needs_clear_bits_);
2931 backbuffer_needs_clear_bits_ = 0;
2932 RestoreClearState();
2937 if (framebuffer_manager()->IsComplete(framebuffer)) {
2941 GLenum completeness = framebuffer->IsPossiblyComplete();
2942 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2944 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
2948 // Are all the attachments cleared?
2949 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2950 texture_manager()->HaveUnclearedMips()) {
2951 if (!framebuffer->IsCleared()) {
2952 // Can we clear them?
2953 if (framebuffer->GetStatus(texture_manager(), target) !=
2954 GL_FRAMEBUFFER_COMPLETE) {
2956 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2957 "framebuffer incomplete (clear)");
2960 ClearUnclearedAttachments(target, framebuffer);
2964 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2965 if (framebuffer->GetStatus(texture_manager(), target) !=
2966 GL_FRAMEBUFFER_COMPLETE) {
2968 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2969 "framebuffer incomplete (check)");
2972 framebuffer_manager()->MarkAsComplete(framebuffer);
2975 // NOTE: At this point we don't know if the framebuffer is complete but
2976 // we DO know that everything that needs to be cleared has been cleared.
2980 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2981 if (!features().chromium_framebuffer_multisample) {
2982 bool valid = CheckFramebufferValid(
2983 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
2991 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
2992 GL_DRAW_FRAMEBUFFER_EXT,
2994 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
2995 GL_READ_FRAMEBUFFER_EXT,
2999 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3000 Framebuffer* framebuffer =
3001 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3002 if (framebuffer != NULL) {
3003 const Framebuffer::Attachment* attachment =
3004 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3006 return gfx::Size(attachment->width(), attachment->height());
3008 return gfx::Size(0, 0);
3009 } else if (offscreen_target_frame_buffer_.get()) {
3010 return offscreen_size_;
3012 return surface_->GetSize();
3016 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3017 Framebuffer* framebuffer =
3018 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3019 if (framebuffer != NULL) {
3020 return framebuffer->GetColorAttachmentTextureType();
3022 return GL_UNSIGNED_BYTE;
3026 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3027 Framebuffer* framebuffer =
3028 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3029 if (framebuffer != NULL) {
3030 return framebuffer->GetColorAttachmentFormat();
3031 } else if (offscreen_target_frame_buffer_.get()) {
3032 return offscreen_target_color_format_;
3034 return back_buffer_color_format_;
3038 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3039 Framebuffer* framebuffer =
3040 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3041 if (framebuffer != NULL) {
3042 return framebuffer->GetColorAttachmentFormat();
3043 } else if (offscreen_target_frame_buffer_.get()) {
3044 return offscreen_target_color_format_;
3046 return back_buffer_color_format_;
3050 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3051 if (!offscreen_saved_color_texture_info_.get())
3053 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3054 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3055 texture_manager()->SetLevelInfo(
3056 offscreen_saved_color_texture_info_.get(),
3060 offscreen_size_.width(),
3061 offscreen_size_.height(),
3067 texture_manager()->SetParameter(
3068 "UpdateParentTextureInfo",
3070 offscreen_saved_color_texture_info_.get(),
3071 GL_TEXTURE_MAG_FILTER,
3073 texture_manager()->SetParameter(
3074 "UpdateParentTextureInfo",
3076 offscreen_saved_color_texture_info_.get(),
3077 GL_TEXTURE_MIN_FILTER,
3079 texture_manager()->SetParameter(
3080 "UpdateParentTextureInfo",
3082 offscreen_saved_color_texture_info_.get(),
3085 texture_manager()->SetParameter(
3086 "UpdateParentTextureInfo",
3088 offscreen_saved_color_texture_info_.get(),
3091 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3093 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3096 void GLES2DecoderImpl::SetResizeCallback(
3097 const base::Callback<void(gfx::Size, float)>& callback) {
3098 resize_callback_ = callback;
3101 Logger* GLES2DecoderImpl::GetLogger() {
3105 void GLES2DecoderImpl::BeginDecoding() {
3106 gpu_tracer_->BeginDecoding();
3107 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3110 void GLES2DecoderImpl::EndDecoding() {
3111 gpu_tracer_->EndDecoding();
3114 ErrorState* GLES2DecoderImpl::GetErrorState() {
3115 return state_.GetErrorState();
3118 void GLES2DecoderImpl::SetShaderCacheCallback(
3119 const ShaderCacheCallback& callback) {
3120 shader_cache_callback_ = callback;
3123 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3124 const WaitSyncPointCallback& callback) {
3125 wait_sync_point_callback_ = callback;
3128 AsyncPixelTransferManager*
3129 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3130 return async_pixel_transfer_manager_.get();
3133 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3134 async_pixel_transfer_manager_.reset();
3137 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3138 AsyncPixelTransferManager* manager) {
3139 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3142 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3143 uint32* service_texture_id) {
3144 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3146 *service_texture_id = texture_ref->service_id();
3152 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3153 return texture_state_.texture_upload_count +
3154 async_pixel_transfer_manager_->GetTextureUploadCount();
3157 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3158 return texture_state_.total_texture_upload_time +
3159 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3162 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3163 return total_processing_commands_time_;
3166 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3167 total_processing_commands_time_ += time;
3170 void GLES2DecoderImpl::Destroy(bool have_context) {
3174 DCHECK(!have_context || context_->IsCurrent(NULL));
3176 // Unbind everything.
3177 state_.vertex_attrib_manager = NULL;
3178 default_vertex_attrib_manager_ = NULL;
3179 state_.texture_units.clear();
3180 state_.bound_array_buffer = NULL;
3181 state_.current_queries.clear();
3182 framebuffer_state_.bound_read_framebuffer = NULL;
3183 framebuffer_state_.bound_draw_framebuffer = NULL;
3184 state_.bound_renderbuffer = NULL;
3186 if (offscreen_saved_color_texture_info_.get()) {
3187 DCHECK(offscreen_target_color_texture_);
3188 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3189 offscreen_saved_color_texture_->id());
3190 offscreen_saved_color_texture_->Invalidate();
3191 offscreen_saved_color_texture_info_ = NULL;
3194 if (copy_texture_CHROMIUM_.get()) {
3195 copy_texture_CHROMIUM_->Destroy();
3196 copy_texture_CHROMIUM_.reset();
3199 if (state_.current_program.get()) {
3200 program_manager()->UnuseProgram(shader_manager(),
3201 state_.current_program.get());
3204 if (attrib_0_buffer_id_) {
3205 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3207 if (fixed_attrib_buffer_id_) {
3208 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3211 if (validation_texture_) {
3212 glDeleteTextures(1, &validation_texture_);
3213 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3214 glDeleteFramebuffersEXT(1, &validation_fbo_);
3217 if (offscreen_target_frame_buffer_.get())
3218 offscreen_target_frame_buffer_->Destroy();
3219 if (offscreen_target_color_texture_.get())
3220 offscreen_target_color_texture_->Destroy();
3221 if (offscreen_target_color_render_buffer_.get())
3222 offscreen_target_color_render_buffer_->Destroy();
3223 if (offscreen_target_depth_render_buffer_.get())
3224 offscreen_target_depth_render_buffer_->Destroy();
3225 if (offscreen_target_stencil_render_buffer_.get())
3226 offscreen_target_stencil_render_buffer_->Destroy();
3227 if (offscreen_saved_frame_buffer_.get())
3228 offscreen_saved_frame_buffer_->Destroy();
3229 if (offscreen_saved_color_texture_.get())
3230 offscreen_saved_color_texture_->Destroy();
3231 if (offscreen_resolved_frame_buffer_.get())
3232 offscreen_resolved_frame_buffer_->Destroy();
3233 if (offscreen_resolved_color_texture_.get())
3234 offscreen_resolved_color_texture_->Destroy();
3236 if (offscreen_target_frame_buffer_.get())
3237 offscreen_target_frame_buffer_->Invalidate();
3238 if (offscreen_target_color_texture_.get())
3239 offscreen_target_color_texture_->Invalidate();
3240 if (offscreen_target_color_render_buffer_.get())
3241 offscreen_target_color_render_buffer_->Invalidate();
3242 if (offscreen_target_depth_render_buffer_.get())
3243 offscreen_target_depth_render_buffer_->Invalidate();
3244 if (offscreen_target_stencil_render_buffer_.get())
3245 offscreen_target_stencil_render_buffer_->Invalidate();
3246 if (offscreen_saved_frame_buffer_.get())
3247 offscreen_saved_frame_buffer_->Invalidate();
3248 if (offscreen_saved_color_texture_.get())
3249 offscreen_saved_color_texture_->Invalidate();
3250 if (offscreen_resolved_frame_buffer_.get())
3251 offscreen_resolved_frame_buffer_->Invalidate();
3252 if (offscreen_resolved_color_texture_.get())
3253 offscreen_resolved_color_texture_->Invalidate();
3256 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3257 // Otherwise, we can leak objects. http://crbug.com/258772.
3258 // state_.current_program must be reset before group_ is reset because
3259 // the later deletes the ProgramManager object that referred by
3260 // state_.current_program object.
3261 state_.current_program = NULL;
3263 copy_texture_CHROMIUM_.reset();
3265 if (query_manager_.get()) {
3266 query_manager_->Destroy(have_context);
3267 query_manager_.reset();
3270 if (vertex_array_manager_ .get()) {
3271 vertex_array_manager_->Destroy(have_context);
3272 vertex_array_manager_.reset();
3275 offscreen_target_frame_buffer_.reset();
3276 offscreen_target_color_texture_.reset();
3277 offscreen_target_color_render_buffer_.reset();
3278 offscreen_target_depth_render_buffer_.reset();
3279 offscreen_target_stencil_render_buffer_.reset();
3280 offscreen_saved_frame_buffer_.reset();
3281 offscreen_saved_color_texture_.reset();
3282 offscreen_resolved_frame_buffer_.reset();
3283 offscreen_resolved_color_texture_.reset();
3285 // Should destroy the transfer manager before the texture manager held
3286 // by the context group.
3287 async_pixel_transfer_manager_.reset();
3290 framebuffer_manager()->RemoveObserver(this);
3291 group_->Destroy(this, have_context);
3295 if (context_.get()) {
3296 context_->ReleaseCurrent(NULL);
3300 #if defined(OS_MACOSX)
3301 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3302 it != texture_to_io_surface_map_.end(); ++it) {
3303 CFRelease(it->second);
3305 texture_to_io_surface_map_.clear();
3309 void GLES2DecoderImpl::SetSurface(
3310 const scoped_refptr<gfx::GLSurface>& surface) {
3311 DCHECK(context_->IsCurrent(NULL));
3312 DCHECK(surface_.get());
3314 RestoreCurrentFramebufferBindings();
3317 bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3318 if (!offscreen_saved_color_texture_.get())
3320 if (!offscreen_saved_color_texture_info_.get()) {
3321 GLuint service_id = offscreen_saved_color_texture_->id();
3322 offscreen_saved_color_texture_info_ = TextureRef::Create(
3323 texture_manager(), 0, service_id);
3324 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3326 UpdateParentTextureInfo();
3328 gpu::gles2::MailboxName name;
3329 memcpy(name.key, mailbox.name, sizeof(mailbox.name));
3330 return mailbox_manager()->ProduceTexture(
3331 GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
3334 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3335 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3336 if (!is_offscreen) {
3337 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3338 << " with an onscreen framebuffer.";
3342 if (offscreen_size_ == size)
3345 offscreen_size_ = size;
3346 int w = offscreen_size_.width();
3347 int h = offscreen_size_.height();
3348 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3349 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3350 << "to allocate storage due to excessive dimensions.";
3354 // Reallocate the offscreen target buffers.
3355 DCHECK(offscreen_target_color_format_);
3356 if (IsOffscreenBufferMultisampled()) {
3357 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3358 feature_info_, offscreen_size_, offscreen_target_color_format_,
3359 offscreen_target_samples_)) {
3360 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3361 << "to allocate storage for offscreen target color buffer.";
3365 if (!offscreen_target_color_texture_->AllocateStorage(
3366 offscreen_size_, offscreen_target_color_format_, false)) {
3367 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3368 << "to allocate storage for offscreen target color texture.";
3372 if (offscreen_target_depth_format_ &&
3373 !offscreen_target_depth_render_buffer_->AllocateStorage(
3374 feature_info_, offscreen_size_, offscreen_target_depth_format_,
3375 offscreen_target_samples_)) {
3376 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3377 << "to allocate storage for offscreen target depth buffer.";
3380 if (offscreen_target_stencil_format_ &&
3381 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3382 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
3383 offscreen_target_samples_)) {
3384 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3385 << "to allocate storage for offscreen target stencil buffer.";
3389 // Attach the offscreen target buffers to the target frame buffer.
3390 if (IsOffscreenBufferMultisampled()) {
3391 offscreen_target_frame_buffer_->AttachRenderBuffer(
3392 GL_COLOR_ATTACHMENT0,
3393 offscreen_target_color_render_buffer_.get());
3395 offscreen_target_frame_buffer_->AttachRenderTexture(
3396 offscreen_target_color_texture_.get());
3398 if (offscreen_target_depth_format_) {
3399 offscreen_target_frame_buffer_->AttachRenderBuffer(
3400 GL_DEPTH_ATTACHMENT,
3401 offscreen_target_depth_render_buffer_.get());
3403 const bool packed_depth_stencil =
3404 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3405 if (packed_depth_stencil) {
3406 offscreen_target_frame_buffer_->AttachRenderBuffer(
3407 GL_STENCIL_ATTACHMENT,
3408 offscreen_target_depth_render_buffer_.get());
3409 } else if (offscreen_target_stencil_format_) {
3410 offscreen_target_frame_buffer_->AttachRenderBuffer(
3411 GL_STENCIL_ATTACHMENT,
3412 offscreen_target_stencil_render_buffer_.get());
3415 if (offscreen_target_frame_buffer_->CheckStatus() !=
3416 GL_FRAMEBUFFER_COMPLETE) {
3417 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3418 << "because offscreen FBO was incomplete.";
3422 // Clear the target frame buffer.
3424 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3425 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3426 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3427 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3429 glStencilMaskSeparate(GL_FRONT, -1);
3430 glStencilMaskSeparate(GL_BACK, -1);
3432 glDepthMask(GL_TRUE);
3433 glDisable(GL_SCISSOR_TEST);
3434 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3435 RestoreClearState();
3438 // Destroy the offscreen resolved framebuffers.
3439 if (offscreen_resolved_frame_buffer_.get())
3440 offscreen_resolved_frame_buffer_->Destroy();
3441 if (offscreen_resolved_color_texture_.get())
3442 offscreen_resolved_color_texture_->Destroy();
3443 offscreen_resolved_color_texture_.reset();
3444 offscreen_resolved_frame_buffer_.reset();
3449 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3450 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3451 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3452 return error::kDeferCommandUntilLater;
3454 GLuint width = static_cast<GLuint>(c.width);
3455 GLuint height = static_cast<GLuint>(c.height);
3456 GLfloat scale_factor = c.scale_factor;
3457 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3459 width = std::max(1U, width);
3460 height = std::max(1U, height);
3462 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3463 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3464 // Make sure that we are done drawing to the back buffer before resizing.
3467 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3469 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3470 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3471 << "ResizeOffscreenFrameBuffer failed.";
3472 return error::kLostContext;
3476 if (!resize_callback_.is_null()) {
3477 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3478 DCHECK(context_->IsCurrent(surface_.get()));
3479 if (!context_->IsCurrent(surface_.get())) {
3480 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3481 << "current after resize callback.";
3482 return error::kLostContext;
3486 return error::kNoError;
3489 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3490 if (command_id > kStartPoint && command_id < kNumCommands) {
3491 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3493 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3496 // Decode command with its arguments, and call the corresponding GL function.
3497 // Note: args is a pointer to the command buffer. As such, it could be changed
3498 // by a (malicious) client at any time, so if validation has to happen, it
3499 // should operate on a copy of them.
3500 error::Error GLES2DecoderImpl::DoCommand(
3501 unsigned int command,
3502 unsigned int arg_count,
3503 const void* cmd_data) {
3504 error::Error result = error::kNoError;
3505 if (log_commands()) {
3506 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3507 // VLOG(1), no luck.
3508 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3509 << GetCommandName(command);
3511 unsigned int command_index = command - kStartPoint - 1;
3512 if (command_index < arraysize(g_command_info)) {
3513 const CommandInfo& info = g_command_info[command_index];
3514 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3515 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3516 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3517 bool doing_gpu_trace = false;
3518 if (gpu_trace_commands_) {
3519 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3520 doing_gpu_trace = true;
3521 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3525 uint32 immediate_data_size =
3526 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3528 #define GLES2_CMD_OP(name) \
3529 case cmds::name::kCmdId: \
3530 result = Handle ## name( \
3531 immediate_data_size, \
3532 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3535 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3539 if (doing_gpu_trace)
3540 gpu_tracer_->End(kTraceDecoder);
3544 while ((error = glGetError()) != GL_NO_ERROR) {
3545 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3546 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3547 << GetCommandName(command);
3548 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3552 result = error::kInvalidArguments;
3555 result = DoCommonCommand(command, arg_count, cmd_data);
3557 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3558 result = current_decoder_error_;
3559 current_decoder_error_ = error::kNoError;
3564 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3565 buffer_manager()->RemoveBuffer(client_id);
3568 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3569 if (GetProgram(client_id)) {
3572 GLuint service_id = glCreateProgram();
3573 if (service_id != 0) {
3574 CreateProgram(client_id, service_id);
3579 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3580 if (GetShader(client_id)) {
3583 GLuint service_id = glCreateShader(type);
3584 if (service_id != 0) {
3585 CreateShader(client_id, service_id, type);
3590 void GLES2DecoderImpl::DoFinish() {
3592 ProcessPendingReadPixels();
3593 ProcessPendingQueries();
3596 void GLES2DecoderImpl::DoFlush() {
3598 ProcessPendingQueries();
3601 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3602 GLuint texture_index = texture_unit - GL_TEXTURE0;
3603 if (texture_index >= state_.texture_units.size()) {
3604 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3605 "glActiveTexture", texture_unit, "texture_unit");
3608 state_.active_texture_unit = texture_index;
3609 glActiveTexture(texture_unit);
3612 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3613 Buffer* buffer = NULL;
3614 GLuint service_id = 0;
3615 if (client_id != 0) {
3616 buffer = GetBuffer(client_id);
3618 if (!group_->bind_generates_resource()) {
3619 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3620 current_decoder_error_ = error::kGenericError;
3624 // It's a new id so make a buffer buffer for it.
3625 glGenBuffersARB(1, &service_id);
3626 CreateBuffer(client_id, service_id);
3627 buffer = GetBuffer(client_id);
3628 IdAllocatorInterface* id_allocator =
3629 group_->GetIdAllocator(id_namespaces::kBuffers);
3630 id_allocator->MarkAsUsed(client_id);
3633 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3635 if (!buffer_manager()->SetTarget(buffer, target)) {
3637 GL_INVALID_OPERATION,
3638 "glBindBuffer", "buffer bound to more than 1 target");
3641 service_id = buffer->service_id();
3644 case GL_ARRAY_BUFFER:
3645 state_.bound_array_buffer = buffer;
3647 case GL_ELEMENT_ARRAY_BUFFER:
3648 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3651 NOTREACHED(); // Validation should prevent us getting here.
3654 glBindBuffer(target, service_id);
3657 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3658 bool all_draw_buffers) {
3659 Framebuffer* framebuffer =
3660 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3661 if (!all_draw_buffers || !framebuffer) {
3662 return (GLES2Util::GetChannelsForFormat(
3663 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3665 return framebuffer->HasAlphaMRT();
3668 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3669 Framebuffer* framebuffer =
3670 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3672 return framebuffer->HasDepthAttachment();
3674 if (offscreen_target_frame_buffer_.get()) {
3675 return offscreen_target_depth_format_ != 0;
3677 return back_buffer_has_depth_;
3680 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3681 Framebuffer* framebuffer =
3682 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3684 return framebuffer->HasStencilAttachment();
3686 if (offscreen_target_frame_buffer_.get()) {
3687 return offscreen_target_stencil_format_ != 0 ||
3688 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3690 return back_buffer_has_stencil_;
3693 void GLES2DecoderImpl::ApplyDirtyState() {
3694 if (framebuffer_state_.clear_state_dirty) {
3696 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3697 state_.color_mask_alpha &&
3698 BoundFramebufferHasColorAttachmentWithAlpha(true));
3699 bool have_depth = BoundFramebufferHasDepthAttachment();
3700 glDepthMask(state_.depth_mask && have_depth);
3701 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3702 bool have_stencil = BoundFramebufferHasStencilAttachment();
3703 glStencilMaskSeparate(
3704 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3705 glStencilMaskSeparate(
3706 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3708 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3709 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3710 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3711 EnableDisable(GL_BLEND, state_.enable_flags.blend);
3712 framebuffer_state_.clear_state_dirty = false;
3716 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3717 return (offscreen_target_frame_buffer_.get())
3718 ? offscreen_target_frame_buffer_->id()
3719 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3722 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) const {
3723 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3724 "context", logger_.GetLogPrefix());
3725 // Restore the Framebuffer first because of bugs in Intel drivers.
3726 // Intel drivers incorrectly clip the viewport settings to
3727 // the size of the current framebuffer object.
3728 RestoreFramebufferBindings();
3729 state_.RestoreState(prev_state);
3732 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3734 framebuffer_state_.bound_draw_framebuffer.get()
3735 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3736 : GetBackbufferServiceId();
3737 if (!features().chromium_framebuffer_multisample) {
3738 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3740 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3741 service_id = framebuffer_state_.bound_read_framebuffer.get()
3742 ? framebuffer_state_.bound_read_framebuffer->service_id()
3743 : GetBackbufferServiceId();
3744 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3749 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3750 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3752 GLenum target = texture->target();
3753 glBindTexture(target, service_id);
3755 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3757 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3759 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3761 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3762 RestoreTextureUnitBindings(state_.active_texture_unit);
3766 void GLES2DecoderImpl::OnFboChanged() const {
3767 if (workarounds().restore_scissor_on_fbo_change)
3768 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3771 // Called after the FBO is checked for completeness.
3772 void GLES2DecoderImpl::OnUseFramebuffer() const {
3773 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3774 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3775 // The driver forgets the correct scissor when modifying the FBO binding.
3776 glScissor(state_.scissor_x,
3778 state_.scissor_width,
3779 state_.scissor_height);
3781 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3782 // it's unclear how this bug works.
3787 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3788 Framebuffer* framebuffer = NULL;
3789 GLuint service_id = 0;
3790 if (client_id != 0) {
3791 framebuffer = GetFramebuffer(client_id);
3793 if (!group_->bind_generates_resource()) {
3795 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3796 current_decoder_error_ = error::kGenericError;
3800 // It's a new id so make a framebuffer framebuffer for it.
3801 glGenFramebuffersEXT(1, &service_id);
3802 CreateFramebuffer(client_id, service_id);
3803 framebuffer = GetFramebuffer(client_id);
3804 IdAllocatorInterface* id_allocator =
3805 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3806 id_allocator->MarkAsUsed(client_id);
3808 service_id = framebuffer->service_id();
3810 framebuffer->MarkAsValid();
3812 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
3814 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3815 framebuffer_state_.bound_draw_framebuffer = framebuffer;
3818 // vmiura: This looks like dup code
3819 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3820 framebuffer_state_.bound_read_framebuffer = framebuffer;
3823 framebuffer_state_.clear_state_dirty = true;
3825 // If we are rendering to the backbuffer get the FBO id for any simulated
3827 if (framebuffer == NULL) {
3828 service_id = GetBackbufferServiceId();
3831 glBindFramebufferEXT(target, service_id);
3835 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3836 Renderbuffer* renderbuffer = NULL;
3837 GLuint service_id = 0;
3838 if (client_id != 0) {
3839 renderbuffer = GetRenderbuffer(client_id);
3840 if (!renderbuffer) {
3841 if (!group_->bind_generates_resource()) {
3843 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3844 current_decoder_error_ = error::kGenericError;
3848 // It's a new id so make a renderbuffer renderbuffer for it.
3849 glGenRenderbuffersEXT(1, &service_id);
3850 CreateRenderbuffer(client_id, service_id);
3851 renderbuffer = GetRenderbuffer(client_id);
3852 IdAllocatorInterface* id_allocator =
3853 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3854 id_allocator->MarkAsUsed(client_id);
3856 service_id = renderbuffer->service_id();
3858 renderbuffer->MarkAsValid();
3860 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
3861 state_.bound_renderbuffer = renderbuffer;
3862 glBindRenderbufferEXT(target, service_id);
3865 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
3866 TextureRef* texture_ref = NULL;
3867 GLuint service_id = 0;
3868 if (client_id != 0) {
3869 texture_ref = GetTexture(client_id);
3871 if (!group_->bind_generates_resource()) {
3872 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3873 current_decoder_error_ = error::kGenericError;
3877 // It's a new id so make a texture texture for it.
3878 glGenTextures(1, &service_id);
3879 DCHECK_NE(0u, service_id);
3880 CreateTexture(client_id, service_id);
3881 texture_ref = GetTexture(client_id);
3882 IdAllocatorInterface* id_allocator =
3883 group_->GetIdAllocator(id_namespaces::kTextures);
3884 id_allocator->MarkAsUsed(client_id);
3887 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
3889 Texture* texture = texture_ref->texture();
3891 // Check the texture exists
3892 // Check that we are not trying to bind it to a different target.
3893 if (texture->target() != 0 && texture->target() != target) {
3895 GL_INVALID_OPERATION,
3896 "glBindTexture", "texture bound to more than 1 target.");
3899 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3900 if (texture->target() == 0) {
3901 texture_manager()->SetTarget(texture_ref, target);
3903 glBindTexture(target, texture->service_id());
3905 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
3906 unit.bind_target = target;
3909 unit.bound_texture_2d = texture_ref;
3911 case GL_TEXTURE_CUBE_MAP:
3912 unit.bound_texture_cube_map = texture_ref;
3914 case GL_TEXTURE_EXTERNAL_OES:
3915 unit.bound_texture_external_oes = texture_ref;
3917 case GL_TEXTURE_RECTANGLE_ARB:
3918 unit.bound_texture_rectangle_arb = texture_ref;
3921 NOTREACHED(); // Validation should prevent us getting here.
3926 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
3927 if (state_.vertex_attrib_manager->Enable(index, false)) {
3929 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
3930 glDisableVertexAttribArray(index);
3935 "glDisableVertexAttribArray", "index out of range");
3939 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3940 GLsizei numAttachments,
3941 const GLenum* attachments) {
3942 if (!features().ext_discard_framebuffer) {
3943 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3944 "glDiscardFramebufferEXT",
3945 "function not available");
3949 Framebuffer* framebuffer =
3950 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3952 // Validates the attachments. If one of them fails
3953 // the whole command fails.
3954 for (GLsizei i = 0; i < numAttachments; ++i) {
3956 !validators_->attachment.IsValid(attachments[i])) ||
3958 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
3959 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3960 "glDiscardFramebufferEXT", attachments[i], "attachments");
3965 // Marks each one of them as not cleared
3966 for (GLsizei i = 0; i < numAttachments; ++i) {
3968 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
3973 switch (attachments[i]) {
3975 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
3978 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
3979 case GL_STENCIL_EXT:
3980 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
3989 // If the default framebuffer is bound but we are still rendering to an
3990 // FBO, translate attachment names that refer to default framebuffer
3991 // channels to corresponding framebuffer attachments.
3992 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
3993 for (GLsizei i = 0; i < numAttachments; ++i) {
3994 GLenum attachment = attachments[i];
3995 if (!framebuffer && GetBackbufferServiceId()) {
3996 switch (attachment) {
3998 attachment = GL_COLOR_ATTACHMENT0;
4001 attachment = GL_DEPTH_ATTACHMENT;
4003 case GL_STENCIL_EXT:
4004 attachment = GL_STENCIL_ATTACHMENT;
4011 translated_attachments[i] = attachment;
4014 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4017 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4018 if (state_.vertex_attrib_manager->Enable(index, true)) {
4019 glEnableVertexAttribArray(index);
4022 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4026 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4027 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4030 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4032 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4036 if (target == GL_TEXTURE_CUBE_MAP) {
4037 for (int i = 0; i < 6; ++i) {
4038 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4039 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4041 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4046 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4048 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4053 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4054 // Workaround for Mac driver bug. In the large scheme of things setting
4055 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4056 // hit so there's probably no need to make this conditional. The bug appears
4057 // to be that if the filtering mode is set to something that doesn't require
4058 // mipmaps for rendering, or is never set to something other than the default,
4059 // then glGenerateMipmap misbehaves.
4060 if (workarounds().set_texture_filter_before_generating_mipmap) {
4061 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4063 glGenerateMipmapEXT(target);
4064 if (workarounds().set_texture_filter_before_generating_mipmap) {
4065 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4066 texture_ref->texture()->min_filter());
4068 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4069 if (error == GL_NO_ERROR) {
4070 texture_manager()->MarkMipmapsGenerated(texture_ref);
4074 bool GLES2DecoderImpl::GetHelper(
4075 GLenum pname, GLint* params, GLsizei* num_written) {
4076 DCHECK(num_written);
4077 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4079 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4082 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4083 GetBoundReadFrameBufferInternalFormat());
4086 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4089 *params = GLES2Util::GetPreferredGLReadPixelsType(
4090 GetBoundReadFrameBufferInternalFormat(),
4091 GetBoundReadFrameBufferTextureType());
4094 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4097 *params = group_->max_fragment_uniform_vectors();
4100 case GL_MAX_VARYING_VECTORS:
4103 *params = group_->max_varying_vectors();
4106 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4109 *params = group_->max_vertex_uniform_vectors();
4115 case GL_MAX_VIEWPORT_DIMS:
4116 if (offscreen_target_frame_buffer_.get()) {
4119 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4120 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4125 case GL_MAX_SAMPLES:
4128 params[0] = renderbuffer_manager()->max_samples();
4131 case GL_MAX_RENDERBUFFER_SIZE:
4134 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4137 case GL_MAX_TEXTURE_SIZE:
4140 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4143 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4146 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4149 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4152 params[0] = group_->max_color_attachments();
4155 case GL_MAX_DRAW_BUFFERS_ARB:
4158 params[0] = group_->max_draw_buffers();
4165 glGetIntegerv(GL_ALPHA_BITS, &v);
4166 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4173 glGetIntegerv(GL_DEPTH_BITS, &v);
4174 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4177 case GL_STENCIL_BITS:
4181 glGetIntegerv(GL_STENCIL_BITS, &v);
4182 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4185 case GL_COMPRESSED_TEXTURE_FORMATS:
4186 *num_written = validators_->compressed_texture_format.GetValues().size();
4188 for (GLint ii = 0; ii < *num_written; ++ii) {
4189 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4193 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4196 *params = validators_->compressed_texture_format.GetValues().size();
4199 case GL_NUM_SHADER_BINARY_FORMATS:
4202 *params = validators_->shader_binary_format.GetValues().size();
4205 case GL_SHADER_BINARY_FORMATS:
4206 *num_written = validators_->shader_binary_format.GetValues().size();
4208 for (GLint ii = 0; ii < *num_written; ++ii) {
4209 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4213 case GL_SHADER_COMPILER:
4219 case GL_ARRAY_BUFFER_BINDING:
4222 if (state_.bound_array_buffer.get()) {
4223 GLuint client_id = 0;
4224 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4226 *params = client_id;
4232 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4235 if (state_.vertex_attrib_manager->element_array_buffer()) {
4236 GLuint client_id = 0;
4237 buffer_manager()->GetClientId(
4238 state_.vertex_attrib_manager->element_array_buffer()->
4239 service_id(), &client_id);
4240 *params = client_id;
4246 case GL_FRAMEBUFFER_BINDING:
4247 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4250 Framebuffer* framebuffer =
4251 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4253 GLuint client_id = 0;
4254 framebuffer_manager()->GetClientId(
4255 framebuffer->service_id(), &client_id);
4256 *params = client_id;
4262 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4265 Framebuffer* framebuffer =
4266 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4268 GLuint client_id = 0;
4269 framebuffer_manager()->GetClientId(
4270 framebuffer->service_id(), &client_id);
4271 *params = client_id;
4277 case GL_RENDERBUFFER_BINDING:
4280 Renderbuffer* renderbuffer =
4281 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4283 *params = renderbuffer->client_id();
4289 case GL_CURRENT_PROGRAM:
4292 if (state_.current_program.get()) {
4293 GLuint client_id = 0;
4294 program_manager()->GetClientId(
4295 state_.current_program->service_id(), &client_id);
4296 *params = client_id;
4302 case GL_VERTEX_ARRAY_BINDING_OES:
4305 if (state_.vertex_attrib_manager.get() !=
4306 default_vertex_attrib_manager_.get()) {
4307 GLuint client_id = 0;
4308 vertex_array_manager_->GetClientId(
4309 state_.vertex_attrib_manager->service_id(), &client_id);
4310 *params = client_id;
4316 case GL_TEXTURE_BINDING_2D:
4319 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4320 if (unit.bound_texture_2d.get()) {
4321 *params = unit.bound_texture_2d->client_id();
4327 case GL_TEXTURE_BINDING_CUBE_MAP:
4330 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4331 if (unit.bound_texture_cube_map.get()) {
4332 *params = unit.bound_texture_cube_map->client_id();
4338 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4341 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4342 if (unit.bound_texture_external_oes.get()) {
4343 *params = unit.bound_texture_external_oes->client_id();
4349 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4352 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4353 if (unit.bound_texture_rectangle_arb.get()) {
4354 *params = unit.bound_texture_rectangle_arb->client_id();
4360 case GL_UNPACK_FLIP_Y_CHROMIUM:
4363 params[0] = unpack_flip_y_;
4366 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4369 params[0] = unpack_premultiply_alpha_;
4372 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4375 params[0] = unpack_unpremultiply_alpha_;
4379 if (pname >= GL_DRAW_BUFFER0_ARB &&
4380 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4383 Framebuffer* framebuffer =
4384 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4386 params[0] = framebuffer->GetDrawBuffer(pname);
4387 } else { // backbuffer
4388 if (pname == GL_DRAW_BUFFER0_ARB)
4389 params[0] = group_->draw_buffer();
4391 params[0] = GL_NONE;
4396 *num_written = util_.GLGetNumValuesReturned(pname);
4401 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4402 GLenum pname, GLsizei* num_values) {
4403 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4406 return GetHelper(pname, NULL, num_values);
4409 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4410 if (GL_MAX_SAMPLES == pname &&
4411 features().use_img_for_multisampled_render_to_texture) {
4412 return GL_MAX_SAMPLES_IMG;
4417 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4419 GLsizei num_written = 0;
4420 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4421 scoped_ptr<GLint[]> values(new GLint[num_written]);
4422 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4423 GetHelper(pname, values.get(), &num_written);
4425 for (GLsizei ii = 0; ii < num_written; ++ii) {
4426 params[ii] = static_cast<GLboolean>(values[ii]);
4429 pname = AdjustGetPname(pname);
4430 glGetBooleanv(pname, params);
4434 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4436 GLsizei num_written = 0;
4437 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4438 if (GetHelper(pname, NULL, &num_written)) {
4439 scoped_ptr<GLint[]> values(new GLint[num_written]);
4440 GetHelper(pname, values.get(), &num_written);
4441 for (GLsizei ii = 0; ii < num_written; ++ii) {
4442 params[ii] = static_cast<GLfloat>(values[ii]);
4445 pname = AdjustGetPname(pname);
4446 glGetFloatv(pname, params);
4451 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4453 GLsizei num_written;
4454 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4455 !GetHelper(pname, params, &num_written)) {
4456 pname = AdjustGetPname(pname);
4457 glGetIntegerv(pname, params);
4461 void GLES2DecoderImpl::DoGetProgramiv(
4462 GLuint program_id, GLenum pname, GLint* params) {
4463 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4467 program->GetProgramiv(pname, params);
4470 void GLES2DecoderImpl::DoGetBufferParameteriv(
4471 GLenum target, GLenum pname, GLint* params) {
4472 // Just delegate it. Some validation is actually done before this.
4473 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4474 &state_, target, pname, params);
4477 void GLES2DecoderImpl::DoBindAttribLocation(
4478 GLuint program_id, GLuint index, const char* name) {
4479 if (!StringIsValidForGLES(name)) {
4481 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4484 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4486 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4489 if (index >= group_->max_vertex_attribs()) {
4491 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4494 Program* program = GetProgramInfoNotShader(
4495 program_id, "glBindAttribLocation");
4499 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4500 glBindAttribLocation(program->service_id(), index, name);
4503 error::Error GLES2DecoderImpl::HandleBindAttribLocation(
4504 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
4505 GLuint program = static_cast<GLuint>(c.program);
4506 GLuint index = static_cast<GLuint>(c.index);
4507 uint32 name_size = c.data_size;
4508 const char* name = GetSharedMemoryAs<const char*>(
4509 c.name_shm_id, c.name_shm_offset, name_size);
4511 return error::kOutOfBounds;
4513 String name_str(name, name_size);
4514 DoBindAttribLocation(program, index, name_str.c_str());
4515 return error::kNoError;
4518 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4519 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4520 GLuint program = static_cast<GLuint>(c.program);
4521 GLuint index = static_cast<GLuint>(c.index);
4522 Bucket* bucket = GetBucket(c.name_bucket_id);
4523 if (!bucket || bucket->size() == 0) {
4524 return error::kInvalidArguments;
4526 std::string name_str;
4527 if (!bucket->GetAsString(&name_str)) {
4528 return error::kInvalidArguments;
4530 DoBindAttribLocation(program, index, name_str.c_str());
4531 return error::kNoError;
4534 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4535 GLuint program_id, GLint location, const char* name) {
4536 if (!StringIsValidForGLES(name)) {
4539 "glBindUniformLocationCHROMIUM", "Invalid character");
4542 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4544 GL_INVALID_OPERATION,
4545 "glBindUniformLocationCHROMIUM", "reserved prefix");
4548 if (location < 0 || static_cast<uint32>(location) >=
4549 (group_->max_fragment_uniform_vectors() +
4550 group_->max_vertex_uniform_vectors()) * 4) {
4553 "glBindUniformLocationCHROMIUM", "location out of range");
4556 Program* program = GetProgramInfoNotShader(
4557 program_id, "glBindUniformLocationCHROMIUM");
4561 if (!program->SetUniformLocationBinding(name, location)) {
4564 "glBindUniformLocationCHROMIUM", "location out of range");
4568 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4569 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
4570 GLuint program = static_cast<GLuint>(c.program);
4571 GLint location = static_cast<GLint>(c.location);
4572 uint32 name_size = c.data_size;
4573 const char* name = GetSharedMemoryAs<const char*>(
4574 c.name_shm_id, c.name_shm_offset, name_size);
4576 return error::kOutOfBounds;
4578 String name_str(name, name_size);
4579 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4580 return error::kNoError;
4583 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4584 uint32 immediate_data_size,
4585 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4586 GLuint program = static_cast<GLuint>(c.program);
4587 GLint location = static_cast<GLint>(c.location);
4588 Bucket* bucket = GetBucket(c.name_bucket_id);
4589 if (!bucket || bucket->size() == 0) {
4590 return error::kInvalidArguments;
4592 std::string name_str;
4593 if (!bucket->GetAsString(&name_str)) {
4594 return error::kInvalidArguments;
4596 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4597 return error::kNoError;
4600 error::Error GLES2DecoderImpl::HandleDeleteShader(
4601 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4602 GLuint client_id = c.shader;
4604 Shader* shader = GetShader(client_id);
4606 if (!shader->IsDeleted()) {
4607 glDeleteShader(shader->service_id());
4608 shader_manager()->MarkAsDeleted(shader);
4611 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4614 return error::kNoError;
4617 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4618 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4619 GLuint client_id = c.program;
4621 Program* program = GetProgram(client_id);
4623 if (!program->IsDeleted()) {
4624 program_manager()->MarkAsDeleted(shader_manager(), program);
4628 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4631 return error::kNoError;
4634 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4635 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4636 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4637 for (GLsizei ii = 0; ii < n; ++ii) {
4638 id_allocator->FreeID(ids[ii]);
4642 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4643 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4644 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4645 GLsizei n = static_cast<GLsizei>(c.n);
4647 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4648 return error::kOutOfBounds;
4650 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4651 c.ids_shm_id, c.ids_shm_offset, data_size);
4653 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4654 return error::kNoError;
4657 return error::kOutOfBounds;
4659 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4660 return error::kNoError;
4663 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4664 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4665 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4666 if (id_offset == 0) {
4667 for (GLsizei ii = 0; ii < n; ++ii) {
4668 ids[ii] = id_allocator->AllocateID();
4671 for (GLsizei ii = 0; ii < n; ++ii) {
4672 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4673 id_offset = ids[ii] + 1;
4678 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4679 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4680 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4681 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4682 GLsizei n = static_cast<GLsizei>(c.n);
4684 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4685 return error::kOutOfBounds;
4687 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4688 c.ids_shm_id, c.ids_shm_offset, data_size);
4690 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4691 return error::kNoError;
4694 return error::kOutOfBounds;
4696 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4697 return error::kNoError;
4700 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4701 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4702 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4703 for (GLsizei ii = 0; ii < n; ++ii) {
4704 if (!id_allocator->MarkAsUsed(ids[ii])) {
4705 for (GLsizei jj = 0; jj < ii; ++jj) {
4706 id_allocator->FreeID(ids[jj]);
4709 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4710 "attempt to register id that already exists");
4716 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4717 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4718 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4719 GLsizei n = static_cast<GLsizei>(c.n);
4721 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4722 return error::kOutOfBounds;
4724 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4725 c.ids_shm_id, c.ids_shm_offset, data_size);
4727 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4728 return error::kNoError;
4731 return error::kOutOfBounds;
4733 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4734 return error::kNoError;
4737 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4738 DCHECK(!ShouldDeferDraws());
4739 if (CheckBoundFramebuffersValid("glClear")) {
4743 return error::kNoError;
4746 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4747 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4748 GLuint client_renderbuffer_id) {
4749 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4752 GL_INVALID_OPERATION,
4753 "glFramebufferRenderbuffer", "no framebuffer bound");
4756 GLuint service_id = 0;
4757 Renderbuffer* renderbuffer = NULL;
4758 if (client_renderbuffer_id) {
4759 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4760 if (!renderbuffer) {
4762 GL_INVALID_OPERATION,
4763 "glFramebufferRenderbuffer", "unknown renderbuffer");
4766 service_id = renderbuffer->service_id();
4768 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4769 glFramebufferRenderbufferEXT(
4770 target, attachment, renderbuffertarget, service_id);
4771 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4772 if (error == GL_NO_ERROR) {
4773 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4775 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4776 framebuffer_state_.clear_state_dirty = true;
4781 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4782 if (SetCapabilityState(cap, false)) {
4787 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4788 if (SetCapabilityState(cap, true)) {
4793 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4794 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4795 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4796 glDepthRange(znear, zfar);
4799 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
4800 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4801 state_.sample_coverage_invert = (invert != 0);
4802 glSampleCoverage(state_.sample_coverage_value, invert);
4805 // Assumes framebuffer is complete.
4806 void GLES2DecoderImpl::ClearUnclearedAttachments(
4807 GLenum target, Framebuffer* framebuffer) {
4808 if (target == GL_READ_FRAMEBUFFER_EXT) {
4809 // bind this to the DRAW point, clear then bind back to READ
4810 // TODO(gman): I don't think there is any guarantee that an FBO that
4811 // is complete on the READ attachment will be complete as a DRAW
4813 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4814 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
4816 GLbitfield clear_bits = 0;
4817 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
4820 (GLES2Util::GetChannelsForFormat(
4821 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4823 glColorMask(true, true, true, true);
4824 clear_bits |= GL_COLOR_BUFFER_BIT;
4827 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4828 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4831 clear_bits |= GL_STENCIL_BUFFER_BIT;
4834 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4835 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4838 clear_bits |= GL_DEPTH_BUFFER_BIT;
4841 glDisable(GL_SCISSOR_TEST);
4842 glClear(clear_bits);
4844 framebuffer_manager()->MarkAttachmentsAsCleared(
4845 framebuffer, renderbuffer_manager(), texture_manager());
4847 RestoreClearState();
4849 if (target == GL_READ_FRAMEBUFFER_EXT) {
4850 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4851 Framebuffer* draw_framebuffer =
4852 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4853 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4854 GetBackbufferServiceId();
4855 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
4859 void GLES2DecoderImpl::RestoreClearState() {
4860 framebuffer_state_.clear_state_dirty = true;
4862 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4863 state_.color_clear_alpha);
4864 glClearStencil(state_.stencil_clear);
4865 glClearDepth(state_.depth_clear);
4866 if (state_.enable_flags.scissor_test) {
4867 glEnable(GL_SCISSOR_TEST);
4871 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
4872 Framebuffer* framebuffer =
4873 GetFramebufferInfoForTarget(target);
4875 return GL_FRAMEBUFFER_COMPLETE;
4877 GLenum completeness = framebuffer->IsPossiblyComplete();
4878 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4879 return completeness;
4881 return framebuffer->GetStatus(texture_manager(), target);
4884 void GLES2DecoderImpl::DoFramebufferTexture2D(
4885 GLenum target, GLenum attachment, GLenum textarget,
4886 GLuint client_texture_id, GLint level) {
4887 DoFramebufferTexture2DCommon(
4888 "glFramebufferTexture2D", target, attachment,
4889 textarget, client_texture_id, level, 0);
4892 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
4893 GLenum target, GLenum attachment, GLenum textarget,
4894 GLuint client_texture_id, GLint level, GLsizei samples) {
4895 if (!features().multisampled_render_to_texture) {
4897 GL_INVALID_OPERATION,
4898 "glFramebufferTexture2DMultisample", "function not available");
4901 DoFramebufferTexture2DCommon(
4902 "glFramebufferTexture2DMultisample", target, attachment,
4903 textarget, client_texture_id, level, samples);
4906 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
4907 const char* name, GLenum target, GLenum attachment, GLenum textarget,
4908 GLuint client_texture_id, GLint level, GLsizei samples) {
4909 if (samples > renderbuffer_manager()->max_samples()) {
4912 "glFramebufferTexture2DMultisample", "samples too large");
4915 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4918 GL_INVALID_OPERATION,
4919 name, "no framebuffer bound.");
4922 GLuint service_id = 0;
4923 TextureRef* texture_ref = NULL;
4924 if (client_texture_id) {
4925 texture_ref = GetTexture(client_texture_id);
4928 GL_INVALID_OPERATION,
4929 name, "unknown texture_ref");
4932 service_id = texture_ref->service_id();
4935 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
4938 name, "level out of range");
4943 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
4945 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
4947 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4949 if (features().use_img_for_multisampled_render_to_texture) {
4950 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
4951 service_id, level, samples);
4953 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
4954 service_id, level, samples);
4957 GLenum error = LOCAL_PEEK_GL_ERROR(name);
4958 if (error == GL_NO_ERROR) {
4959 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
4962 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4963 framebuffer_state_.clear_state_dirty = true;
4967 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
4972 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4973 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
4974 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4977 GL_INVALID_OPERATION,
4978 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
4981 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4982 const Framebuffer::Attachment* attachment_object =
4983 framebuffer->GetAttachment(attachment);
4984 *params = attachment_object ? attachment_object->object_name() : 0;
4986 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
4987 features().use_img_for_multisampled_render_to_texture) {
4988 pname = GL_TEXTURE_SAMPLES_IMG;
4990 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
4994 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4995 GLenum target, GLenum pname, GLint* params) {
4996 Renderbuffer* renderbuffer =
4997 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4998 if (!renderbuffer) {
5000 GL_INVALID_OPERATION,
5001 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5005 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5006 *params = renderbuffer->internal_format();
5008 case GL_RENDERBUFFER_WIDTH:
5009 *params = renderbuffer->width();
5011 case GL_RENDERBUFFER_HEIGHT:
5012 *params = renderbuffer->height();
5014 case GL_RENDERBUFFER_SAMPLES_EXT:
5015 if (features().use_img_for_multisampled_render_to_texture) {
5016 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5019 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5023 glGetRenderbufferParameterivEXT(target, pname, params);
5028 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5029 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5030 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5031 GLbitfield mask, GLenum filter) {
5032 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5033 if (!features().chromium_framebuffer_multisample) {
5035 GL_INVALID_OPERATION,
5036 "glBlitFramebufferCHROMIUM", "function not available");
5040 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5044 glDisable(GL_SCISSOR_TEST);
5045 BlitFramebufferHelper(
5046 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5047 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
5050 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5051 const FeatureInfo* feature_info,
5054 GLenum internal_format,
5057 // TODO(sievers): This could be resolved at the GL binding level, but the
5058 // binding process is currently a bit too 'brute force'.
5059 if (feature_info->feature_flags().is_angle) {
5060 glRenderbufferStorageMultisampleANGLE(
5061 target, samples, internal_format, width, height);
5062 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5063 glRenderbufferStorageMultisample(
5064 target, samples, internal_format, width, height);
5066 glRenderbufferStorageMultisampleEXT(
5067 target, samples, internal_format, width, height);
5071 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5081 // TODO(sievers): This could be resolved at the GL binding level, but the
5082 // binding process is currently a bit too 'brute force'.
5083 if (feature_info_->feature_flags().is_angle) {
5084 glBlitFramebufferANGLE(
5085 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5086 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5088 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5090 glBlitFramebufferEXT(
5091 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5095 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5097 GLenum internalformat,
5100 if (samples > renderbuffer_manager()->max_samples()) {
5103 "glRenderbufferStorageMultisample", "samples too large");
5107 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5108 height > renderbuffer_manager()->max_renderbuffer_size()) {
5111 "glRenderbufferStorageMultisample", "dimensions too large");
5115 uint32 estimated_size = 0;
5116 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5117 width, height, samples, internalformat, &estimated_size)) {
5120 "glRenderbufferStorageMultsample", "dimensions too large");
5124 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5127 "glRenderbufferStorageMultsample", "out of memory");
5134 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5135 GLenum target, GLsizei samples, GLenum internalformat,
5136 GLsizei width, GLsizei height) {
5137 if (!features().chromium_framebuffer_multisample) {
5138 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5139 "glRenderbufferStorageMultisampleCHROMIUM",
5140 "function not available");
5144 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5145 if (!renderbuffer) {
5146 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5147 "glRenderbufferStorageMultisampleCHROMIUM",
5148 "no renderbuffer bound");
5152 if (!ValidateRenderbufferStorageMultisample(
5153 samples, internalformat, width, height)) {
5157 GLenum impl_format =
5158 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5160 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5161 "glRenderbufferStorageMultisampleCHROMIUM");
5162 RenderbufferStorageMultisampleHelper(
5163 feature_info_, target, samples, impl_format, width, height);
5165 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5166 if (error == GL_NO_ERROR) {
5168 if (workarounds().validate_multisample_buffer_allocation) {
5169 if (!VerifyMultisampleRenderbufferIntegrity(
5170 renderbuffer->service_id(), impl_format)) {
5173 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5178 // TODO(gman): If renderbuffers tracked which framebuffers they were
5179 // attached to we could just mark those framebuffers as not complete.
5180 framebuffer_manager()->IncFramebufferStateChangeCount();
5181 renderbuffer_manager()->SetInfo(
5182 renderbuffer, samples, internalformat, width, height);
5186 // This is the handler for multisampled_render_to_texture extensions.
5187 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5188 GLenum target, GLsizei samples, GLenum internalformat,
5189 GLsizei width, GLsizei height) {
5190 if (!features().multisampled_render_to_texture) {
5192 GL_INVALID_OPERATION,
5193 "glRenderbufferStorageMultisampleEXT", "function not available");
5197 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5198 if (!renderbuffer) {
5199 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5200 "glRenderbufferStorageMultisampleEXT",
5201 "no renderbuffer bound");
5205 if (!ValidateRenderbufferStorageMultisample(
5206 samples, internalformat, width, height)) {
5210 GLenum impl_format =
5211 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5213 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5214 if (features().use_img_for_multisampled_render_to_texture) {
5215 glRenderbufferStorageMultisampleIMG(
5216 target, samples, impl_format, width, height);
5218 glRenderbufferStorageMultisampleEXT(
5219 target, samples, impl_format, width, height);
5221 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5222 if (error == GL_NO_ERROR) {
5223 // TODO(gman): If renderbuffers tracked which framebuffers they were
5224 // attached to we could just mark those framebuffers as not complete.
5225 framebuffer_manager()->IncFramebufferStateChangeCount();
5226 renderbuffer_manager()->SetInfo(
5227 renderbuffer, samples, internalformat, width, height);
5231 // This function validates the allocation of a multisampled renderbuffer
5232 // by clearing it to a key color, blitting the contents to a texture, and
5233 // reading back the color to ensure it matches the key.
5234 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5235 GLuint renderbuffer, GLenum format) {
5237 // Only validate color buffers.
5238 // These formats have been selected because they are very common or are known
5239 // to be used by the WebGL backbuffer. If problems are observed with other
5240 // color formats they can be added here.
5251 GLint draw_framebuffer, read_framebuffer;
5253 // Cache framebuffer and texture bindings.
5254 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5255 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5257 if (!validation_texture_) {
5258 GLint bound_texture;
5259 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5261 // Create additional resources needed for the verification.
5262 glGenTextures(1, &validation_texture_);
5263 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5264 glGenFramebuffersEXT(1, &validation_fbo_);
5266 // Texture only needs to be 1x1.
5267 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5268 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5269 GL_UNSIGNED_BYTE, NULL);
5271 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5272 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5273 GL_TEXTURE_2D, validation_texture_, 0);
5275 glBindTexture(GL_TEXTURE_2D, bound_texture);
5278 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5279 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5280 GL_RENDERBUFFER, renderbuffer);
5282 // Cache current state and reset it to the values we require.
5283 GLboolean scissor_enabled = false;
5284 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5285 if (scissor_enabled)
5286 glDisable(GL_SCISSOR_TEST);
5288 GLboolean color_mask[4] = {true, true, true, true};
5289 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5290 glColorMask(true, true, true, true);
5292 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5293 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5294 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5296 // Clear the buffer to the desired key color.
5297 glClear(GL_COLOR_BUFFER_BIT);
5299 // Blit from the multisample buffer to a standard texture.
5300 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5301 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5303 BlitFramebufferHelper(
5304 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5306 // Read a pixel from the buffer.
5307 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5309 unsigned char pixel[3] = {0, 0, 0};
5310 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5312 // Detach the renderbuffer.
5313 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5314 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5315 GL_RENDERBUFFER, 0);
5317 // Restore cached state.
5318 if (scissor_enabled)
5319 glEnable(GL_SCISSOR_TEST);
5321 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5322 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5323 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5324 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5326 // Return true if the pixel matched the desired key color.
5327 return (pixel[0] == 0xFF &&
5332 void GLES2DecoderImpl::DoRenderbufferStorage(
5333 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5334 Renderbuffer* renderbuffer =
5335 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5336 if (!renderbuffer) {
5338 GL_INVALID_OPERATION,
5339 "glRenderbufferStorage", "no renderbuffer bound");
5343 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5344 height > renderbuffer_manager()->max_renderbuffer_size()) {
5346 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5350 uint32 estimated_size = 0;
5351 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5352 width, height, 1, internalformat, &estimated_size)) {
5354 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5358 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5360 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5364 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5365 glRenderbufferStorageEXT(
5367 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5371 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5372 if (error == GL_NO_ERROR) {
5373 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5374 // we could just mark those framebuffers as not complete.
5375 framebuffer_manager()->IncFramebufferStateChangeCount();
5376 renderbuffer_manager()->SetInfo(
5377 renderbuffer, 1, internalformat, width, height);
5381 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5382 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5383 Program* program = GetProgramInfoNotShader(
5384 program_id, "glLinkProgram");
5389 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5390 ShaderTranslator* vertex_translator = NULL;
5391 ShaderTranslator* fragment_translator = NULL;
5392 if (use_shader_translator_) {
5393 vertex_translator = vertex_translator_.get();
5394 fragment_translator = fragment_translator_.get();
5396 if (program->Link(shader_manager(),
5398 fragment_translator,
5399 feature_info_.get(),
5400 shader_cache_callback_)) {
5401 if (program == state_.current_program.get()) {
5402 if (workarounds().use_current_program_after_successful_link) {
5403 glUseProgram(program->service_id());
5405 program_manager()->ClearUniforms(program);
5410 void GLES2DecoderImpl::DoTexParameterf(
5411 GLenum target, GLenum pname, GLfloat param) {
5412 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5415 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5419 texture_manager()->SetParameter(
5420 "glTexParameterf", GetErrorState(), texture, pname,
5421 static_cast<GLint>(param));
5424 void GLES2DecoderImpl::DoTexParameteri(
5425 GLenum target, GLenum pname, GLint param) {
5426 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5429 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5433 texture_manager()->SetParameter(
5434 "glTexParameteri", GetErrorState(), texture, pname, param);
5437 void GLES2DecoderImpl::DoTexParameterfv(
5438 GLenum target, GLenum pname, const GLfloat* params) {
5439 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5442 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5446 texture_manager()->SetParameter(
5447 "glTexParameterfv", GetErrorState(), texture, pname,
5448 static_cast<GLint>(params[0]));
5451 void GLES2DecoderImpl::DoTexParameteriv(
5452 GLenum target, GLenum pname, const GLint* params) {
5453 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5457 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5461 texture_manager()->SetParameter(
5462 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5465 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5466 if (!state_.current_program.get()) {
5467 // The program does not exist.
5469 GL_INVALID_OPERATION, function_name, "no program in use");
5472 if (!state_.current_program->InUse()) {
5474 GL_INVALID_OPERATION, function_name, "program not linked");
5480 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5481 GLint location, const char* function_name) {
5482 if (!CheckCurrentProgram(function_name)) {
5485 return location != -1;
5490 static const GLenum valid_int_vec1_types_list[] = {
5494 GL_SAMPLER_2D_RECT_ARB,
5496 GL_SAMPLER_EXTERNAL_OES,
5499 static const GLenum valid_int_vec2_types_list[] = {
5504 static const GLenum valid_int_vec3_types_list[] = {
5509 static const GLenum valid_int_vec4_types_list[] = {
5514 static const GLenum valid_float_vec1_types_list[] = {
5519 static const GLenum valid_float_vec2_types_list[] = {
5524 static const GLenum valid_float_vec3_types_list[] = {
5529 static const GLenum valid_float_vec4_types_list[] = {
5534 static const GLenum valid_float_mat2_types_list[] = {
5538 static const GLenum valid_float_mat3_types_list[] = {
5542 static const GLenum valid_float_mat4_types_list[] = {
5546 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5547 valid_int_vec1_types_list,
5548 arraysize(valid_int_vec1_types_list),
5551 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5552 valid_int_vec2_types_list,
5553 arraysize(valid_int_vec2_types_list),
5556 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5557 valid_int_vec3_types_list,
5558 arraysize(valid_int_vec3_types_list),
5561 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5562 valid_int_vec4_types_list,
5563 arraysize(valid_int_vec4_types_list),
5566 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5567 valid_float_vec1_types_list,
5568 arraysize(valid_float_vec1_types_list),
5571 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5572 valid_float_vec2_types_list,
5573 arraysize(valid_float_vec2_types_list),
5576 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5577 valid_float_vec3_types_list,
5578 arraysize(valid_float_vec3_types_list),
5581 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5582 valid_float_vec4_types_list,
5583 arraysize(valid_float_vec4_types_list),
5586 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5587 valid_float_mat2_types_list,
5588 arraysize(valid_float_mat2_types_list),
5591 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5592 valid_float_mat3_types_list,
5593 arraysize(valid_float_mat3_types_list),
5596 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5597 valid_float_mat4_types_list,
5598 arraysize(valid_float_mat4_types_list),
5601 } // anonymous namespace.
5603 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5604 GLint fake_location, const char* function_name,
5605 const GLES2DecoderImpl::BaseUniformInfo& base_info,
5606 GLint* real_location, GLenum* type, GLsizei* count) {
5609 DCHECK(real_location);
5611 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5614 GLint array_index = -1;
5615 const Program::UniformInfo* info =
5616 state_.current_program->GetUniformInfoByFakeLocation(
5617 fake_location, real_location, &array_index);
5620 GL_INVALID_OPERATION, function_name, "unknown location");
5624 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5625 if (base_info.valid_types[ii] == info->type) {
5632 GL_INVALID_OPERATION, function_name,
5633 "wrong uniform function for type");
5636 if (*count > 1 && !info->is_array) {
5638 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5641 *count = std::min(info->size - array_index, *count);
5649 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5652 GLint real_location = -1;
5653 if (!PrepForSetUniformByLocation(
5654 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5655 &real_location, &type, &count)) {
5658 if (!state_.current_program->SetSamplers(
5659 state_.texture_units.size(), fake_location, 1, &v0)) {
5661 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5664 glUniform1i(real_location, v0);
5667 void GLES2DecoderImpl::DoUniform1iv(
5668 GLint fake_location, GLsizei count, const GLint *value) {
5670 GLint real_location = -1;
5671 if (!PrepForSetUniformByLocation(
5672 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5673 &real_location, &type, &count)) {
5676 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5677 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5678 if (!state_.current_program->SetSamplers(
5679 state_.texture_units.size(), fake_location, count, value)) {
5681 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5685 glUniform1iv(real_location, count, value);
5688 void GLES2DecoderImpl::DoUniform1fv(
5689 GLint fake_location, GLsizei count, const GLfloat* value) {
5691 GLint real_location = -1;
5692 if (!PrepForSetUniformByLocation(
5693 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5694 &real_location, &type, &count)) {
5697 if (type == GL_BOOL) {
5698 scoped_ptr<GLint[]> temp(new GLint[count]);
5699 for (GLsizei ii = 0; ii < count; ++ii) {
5700 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5702 DoUniform1iv(real_location, count, temp.get());
5704 glUniform1fv(real_location, count, value);
5708 void GLES2DecoderImpl::DoUniform2fv(
5709 GLint fake_location, GLsizei count, const GLfloat* value) {
5711 GLint real_location = -1;
5712 if (!PrepForSetUniformByLocation(
5713 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5714 &real_location, &type, &count)) {
5717 if (type == GL_BOOL_VEC2) {
5718 GLsizei num_values = count * 2;
5719 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5720 for (GLsizei ii = 0; ii < num_values; ++ii) {
5721 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5723 glUniform2iv(real_location, count, temp.get());
5725 glUniform2fv(real_location, count, value);
5729 void GLES2DecoderImpl::DoUniform3fv(
5730 GLint fake_location, GLsizei count, const GLfloat* value) {
5732 GLint real_location = -1;
5733 if (!PrepForSetUniformByLocation(
5734 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5735 &real_location, &type, &count)) {
5738 if (type == GL_BOOL_VEC3) {
5739 GLsizei num_values = count * 3;
5740 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5741 for (GLsizei ii = 0; ii < num_values; ++ii) {
5742 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5744 glUniform3iv(real_location, count, temp.get());
5746 glUniform3fv(real_location, count, value);
5750 void GLES2DecoderImpl::DoUniform4fv(
5751 GLint fake_location, GLsizei count, const GLfloat* value) {
5753 GLint real_location = -1;
5754 if (!PrepForSetUniformByLocation(
5755 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5756 &real_location, &type, &count)) {
5759 if (type == GL_BOOL_VEC4) {
5760 GLsizei num_values = count * 4;
5761 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5762 for (GLsizei ii = 0; ii < num_values; ++ii) {
5763 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5765 glUniform4iv(real_location, count, temp.get());
5767 glUniform4fv(real_location, count, value);
5771 void GLES2DecoderImpl::DoUniform2iv(
5772 GLint fake_location, GLsizei count, const GLint* value) {
5774 GLint real_location = -1;
5775 if (!PrepForSetUniformByLocation(
5776 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5777 &real_location, &type, &count)) {
5780 glUniform2iv(real_location, count, value);
5783 void GLES2DecoderImpl::DoUniform3iv(
5784 GLint fake_location, GLsizei count, const GLint* value) {
5786 GLint real_location = -1;
5787 if (!PrepForSetUniformByLocation(
5788 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5789 &real_location, &type, &count)) {
5792 glUniform3iv(real_location, count, value);
5795 void GLES2DecoderImpl::DoUniform4iv(
5796 GLint fake_location, GLsizei count, const GLint* value) {
5798 GLint real_location = -1;
5799 if (!PrepForSetUniformByLocation(
5800 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5801 &real_location, &type, &count)) {
5804 glUniform4iv(real_location, count, value);
5807 void GLES2DecoderImpl::DoUniformMatrix2fv(
5808 GLint fake_location, GLsizei count, GLboolean transpose,
5809 const GLfloat* value) {
5811 GLint real_location = -1;
5812 if (!PrepForSetUniformByLocation(
5813 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5814 &real_location, &type, &count)) {
5817 glUniformMatrix2fv(real_location, count, transpose, value);
5820 void GLES2DecoderImpl::DoUniformMatrix3fv(
5821 GLint fake_location, GLsizei count, GLboolean transpose,
5822 const GLfloat* value) {
5824 GLint real_location = -1;
5825 if (!PrepForSetUniformByLocation(
5826 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5827 &real_location, &type, &count)) {
5830 glUniformMatrix3fv(real_location, count, transpose, value);
5833 void GLES2DecoderImpl::DoUniformMatrix4fv(
5834 GLint fake_location, GLsizei count, GLboolean transpose,
5835 const GLfloat* value) {
5837 GLint real_location = -1;
5838 if (!PrepForSetUniformByLocation(
5839 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5840 &real_location, &type, &count)) {
5843 glUniformMatrix4fv(real_location, count, transpose, value);
5846 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5847 GLuint service_id = 0;
5848 Program* program = NULL;
5850 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5854 if (!program->IsValid()) {
5855 // Program was not linked successfully. (ie, glLinkProgram)
5857 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5860 service_id = program->service_id();
5862 if (state_.current_program.get()) {
5863 program_manager()->UnuseProgram(shader_manager(),
5864 state_.current_program.get());
5866 state_.current_program = program;
5867 LogClientServiceMapping("glUseProgram", program_id, service_id);
5868 glUseProgram(service_id);
5869 if (state_.current_program.get()) {
5870 program_manager()->UseProgram(state_.current_program.get());
5874 void GLES2DecoderImpl::RenderWarning(
5875 const char* filename, int line, const std::string& msg) {
5876 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
5879 void GLES2DecoderImpl::PerformanceWarning(
5880 const char* filename, int line, const std::string& msg) {
5881 logger_.LogMessage(filename, line,
5882 std::string("PERFORMANCE WARNING: ") + msg);
5885 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5886 Texture* texture, GLenum textarget) {
5887 // This might be supported in the future.
5888 if (textarget != GL_TEXTURE_2D)
5890 // Image is already in use if texture is attached to a framebuffer.
5891 if (texture && !texture->IsAttachedToFramebuffer()) {
5892 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5894 ScopedGLErrorSuppressor suppressor(
5895 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5897 glBindTexture(textarget, texture->service_id());
5898 image->WillUseTexImage();
5899 RestoreCurrentTexture2DBindings(&state_);
5904 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
5905 Texture* texture, GLenum textarget) {
5906 // This might be supported in the future.
5907 if (textarget != GL_TEXTURE_2D)
5909 // Image is still in use if texture is attached to a framebuffer.
5910 if (texture && !texture->IsAttachedToFramebuffer()) {
5911 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5913 ScopedGLErrorSuppressor suppressor(
5914 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
5916 glBindTexture(textarget, texture->service_id());
5917 image->DidUseTexImage();
5918 RestoreCurrentTexture2DBindings(&state_);
5923 bool GLES2DecoderImpl::PrepareTexturesForRender() {
5924 DCHECK(state_.current_program.get());
5925 if (!texture_manager()->HaveUnrenderableTextures() &&
5926 !texture_manager()->HaveImages()) {
5930 bool textures_set = false;
5931 const Program::SamplerIndices& sampler_indices =
5932 state_.current_program->sampler_indices();
5933 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5934 const Program::UniformInfo* uniform_info =
5935 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5936 DCHECK(uniform_info);
5937 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5938 GLuint texture_unit_index = uniform_info->texture_units[jj];
5939 if (texture_unit_index < state_.texture_units.size()) {
5940 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5941 TextureRef* texture_ref =
5942 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5943 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
5944 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
5945 textures_set = true;
5946 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5949 texture_manager()->black_texture_id(uniform_info->type));
5950 LOCAL_RENDER_WARNING(
5951 std::string("texture bound to texture unit ") +
5952 base::IntToString(texture_unit_index) +
5953 " is not renderable. It maybe non-power-of-2 and have"
5954 " incompatible texture filtering or is not"
5955 " 'texture complete'");
5959 Texture* texture = texture_ref->texture();
5960 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5961 if (image && !texture->IsAttachedToFramebuffer()) {
5962 ScopedGLErrorSuppressor suppressor(
5963 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
5964 textures_set = true;
5965 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5966 image->WillUseTexImage();
5970 // else: should this be an error?
5973 return !textures_set;
5976 void GLES2DecoderImpl::RestoreStateForTextures() {
5977 DCHECK(state_.current_program.get());
5978 const Program::SamplerIndices& sampler_indices =
5979 state_.current_program->sampler_indices();
5980 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5981 const Program::UniformInfo* uniform_info =
5982 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5983 DCHECK(uniform_info);
5984 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5985 GLuint texture_unit_index = uniform_info->texture_units[jj];
5986 if (texture_unit_index < state_.texture_units.size()) {
5987 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5988 TextureRef* texture_ref =
5989 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5990 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
5991 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5992 // Get the texture_ref info that was previously bound here.
5993 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
5994 ? texture_unit.bound_texture_2d.get()
5995 : texture_unit.bound_texture_cube_map.get();
5996 glBindTexture(texture_unit.bind_target,
5997 texture_ref ? texture_ref->service_id() : 0);
6001 Texture* texture = texture_ref->texture();
6002 gfx::GLImage* image =
6003 texture->GetLevelImage(texture_unit.bind_target, 0);
6004 if (image && !texture->IsAttachedToFramebuffer()) {
6005 ScopedGLErrorSuppressor suppressor(
6006 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6007 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6008 image->DidUseTexImage();
6014 // Set the active texture back to whatever the user had it as.
6015 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6018 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6019 // Only check if there are some uncleared textures.
6020 if (!texture_manager()->HaveUnsafeTextures()) {
6024 // 1: Check all textures we are about to render with.
6025 if (state_.current_program.get()) {
6026 const Program::SamplerIndices& sampler_indices =
6027 state_.current_program->sampler_indices();
6028 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6029 const Program::UniformInfo* uniform_info =
6030 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6031 DCHECK(uniform_info);
6032 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6033 GLuint texture_unit_index = uniform_info->texture_units[jj];
6034 if (texture_unit_index < state_.texture_units.size()) {
6035 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6036 TextureRef* texture_ref =
6037 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6038 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6039 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6050 bool GLES2DecoderImpl::IsDrawValid(
6051 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
6052 // NOTE: We specifically do not check current_program->IsValid() because
6053 // it could never be invalid since glUseProgram would have failed. While
6054 // glLinkProgram could later mark the program as invalid the previous
6055 // valid program will still function if it is still the current program.
6056 if (!state_.current_program.get()) {
6057 // The program does not exist.
6058 // But GL says no ERROR.
6059 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6063 return state_.vertex_attrib_manager
6064 ->ValidateBindings(function_name,
6066 feature_info_.get(),
6067 state_.current_program.get(),
6068 max_vertex_accessed,
6072 bool GLES2DecoderImpl::SimulateAttrib0(
6073 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6077 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6080 const VertexAttrib* attrib =
6081 state_.vertex_attrib_manager->GetVertexAttrib(0);
6082 // If it's enabled or it's not used then we don't need to do anything.
6083 bool attrib_0_used =
6084 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6085 if (attrib->enabled() && attrib_0_used) {
6089 // Make a buffer with a single repeated vec4 value enough to
6090 // simulate the constant value that is supposed to be here.
6091 // This is required to emulate GLES2 on GL.
6092 GLuint num_vertices = max_vertex_accessed + 1;
6093 uint32 size_needed = 0;
6095 if (num_vertices == 0 ||
6096 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6097 size_needed > 0x7FFFFFFFU) {
6098 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6102 LOCAL_PERFORMANCE_WARNING(
6103 "Attribute 0 is disabled. This has signficant performance penalty");
6105 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6106 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6108 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6110 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6111 GLenum error = glGetError();
6112 if (error != GL_NO_ERROR) {
6114 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6119 const Vec4& value = state_.attrib_values[0];
6122 (!attrib_0_buffer_matches_value_ ||
6123 (value.v[0] != attrib_0_value_.v[0] ||
6124 value.v[1] != attrib_0_value_.v[1] ||
6125 value.v[2] != attrib_0_value_.v[2] ||
6126 value.v[3] != attrib_0_value_.v[3])))) {
6127 std::vector<Vec4> temp(num_vertices, value);
6128 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6129 attrib_0_buffer_matches_value_ = true;
6130 attrib_0_value_ = value;
6131 attrib_0_size_ = size_needed;
6134 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6136 if (attrib->divisor())
6137 glVertexAttribDivisorANGLE(0, 0);
6143 void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
6144 const VertexAttrib* attrib =
6145 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6146 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6147 Buffer* buffer = attrib->buffer();
6148 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6149 glVertexAttribPointer(
6150 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6151 attrib->gl_stride(), ptr);
6152 if (attrib->divisor())
6153 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6156 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6159 // Never touch vertex attribute 0's state (in particular, never
6160 // disable it) when running on desktop GL because it will never be
6162 if (attrib_index != 0 ||
6163 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6164 if (attrib->enabled()) {
6165 glEnableVertexAttribArray(attrib_index);
6167 glDisableVertexAttribArray(attrib_index);
6172 bool GLES2DecoderImpl::SimulateFixedAttribs(
6173 const char* function_name,
6174 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6177 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6180 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6184 LOCAL_PERFORMANCE_WARNING(
6185 "GL_FIXED attributes have a signficant performance penalty");
6187 // NOTE: we could be smart and try to check if a buffer is used
6188 // twice in 2 different attribs, find the overlapping parts and therefore
6189 // duplicate the minimum amount of data but this whole code path is not meant
6190 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6191 // tests so we just add to the buffer attrib used.
6193 GLuint elements_needed = 0;
6194 const VertexAttribManager::VertexAttribList& enabled_attribs =
6195 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6196 for (VertexAttribManager::VertexAttribList::const_iterator it =
6197 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6198 const VertexAttrib* attrib = *it;
6199 const Program::VertexAttrib* attrib_info =
6200 state_.current_program->GetAttribInfoByLocation(attrib->index());
6201 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6202 max_vertex_accessed);
6203 GLuint num_vertices = max_accessed + 1;
6204 if (num_vertices == 0) {
6206 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6210 attrib->CanAccess(max_accessed) &&
6211 attrib->type() == GL_FIXED) {
6212 uint32 elements_used = 0;
6213 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6214 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6216 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6222 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6223 uint32 size_needed = 0;
6224 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6225 size_needed > 0x7FFFFFFFU) {
6227 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6231 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6233 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6234 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6235 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6236 GLenum error = glGetError();
6237 if (error != GL_NO_ERROR) {
6239 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6244 // Copy the elements and convert to float
6245 GLintptr offset = 0;
6246 for (VertexAttribManager::VertexAttribList::const_iterator it =
6247 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6248 const VertexAttrib* attrib = *it;
6249 const Program::VertexAttrib* attrib_info =
6250 state_.current_program->GetAttribInfoByLocation(attrib->index());
6251 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6252 max_vertex_accessed);
6253 GLuint num_vertices = max_accessed + 1;
6254 if (num_vertices == 0) {
6256 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6260 attrib->CanAccess(max_accessed) &&
6261 attrib->type() == GL_FIXED) {
6262 int num_elements = attrib->size() * kSizeOfFloat;
6263 int size = num_elements * num_vertices;
6264 scoped_ptr<float[]> data(new float[size]);
6265 const int32* src = reinterpret_cast<const int32 *>(
6266 attrib->buffer()->GetRange(attrib->offset(), size));
6267 const int32* end = src + num_elements;
6268 float* dst = data.get();
6269 while (src != end) {
6270 *dst++ = static_cast<float>(*src++) / 65536.0f;
6272 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6273 glVertexAttribPointer(
6274 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6275 reinterpret_cast<GLvoid*>(offset));
6283 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6284 // There's no need to call glVertexAttribPointer because we shadow all the
6285 // settings and passing GL_FIXED to it will not work.
6288 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6292 error::Error GLES2DecoderImpl::DoDrawArrays(
6293 const char* function_name,
6298 GLsizei primcount) {
6299 error::Error error = WillAccessBoundFramebufferForDraw();
6300 if (error != error::kNoError)
6302 if (!validators_->draw_mode.IsValid(mode)) {
6303 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6304 return error::kNoError;
6307 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6308 return error::kNoError;
6310 if (primcount < 0) {
6311 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6312 return error::kNoError;
6314 if (!CheckBoundFramebuffersValid(function_name)) {
6315 return error::kNoError;
6317 // We have to check this here because the prototype for glDrawArrays
6318 // is GLint not GLsizei.
6320 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6321 return error::kNoError;
6324 if (count == 0 || (instanced && primcount == 0)) {
6325 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6326 return error::kNoError;
6329 GLuint max_vertex_accessed = first + count - 1;
6330 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6331 if (!ClearUnclearedTextures()) {
6332 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6333 return error::kNoError;
6335 bool simulated_attrib_0 = false;
6336 if (!SimulateAttrib0(
6337 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6338 return error::kNoError;
6340 bool simulated_fixed_attribs = false;
6341 if (SimulateFixedAttribs(
6342 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6344 bool textures_set = !PrepareTexturesForRender();
6347 glDrawArrays(mode, first, count);
6349 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6351 ProcessPendingQueries();
6353 RestoreStateForTextures();
6355 if (simulated_fixed_attribs) {
6356 RestoreStateForSimulatedFixedAttribs();
6359 if (simulated_attrib_0) {
6360 RestoreStateForAttrib(0);
6363 return error::kNoError;
6366 error::Error GLES2DecoderImpl::HandleDrawArrays(
6367 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6368 return DoDrawArrays("glDrawArrays",
6370 static_cast<GLenum>(c.mode),
6371 static_cast<GLint>(c.first),
6372 static_cast<GLsizei>(c.count),
6376 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6377 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6378 if (!features().angle_instanced_arrays) {
6380 GL_INVALID_OPERATION,
6381 "glDrawArraysInstancedANGLE", "function not available");
6382 return error::kNoError;
6384 return DoDrawArrays("glDrawArraysIntancedANGLE",
6386 static_cast<GLenum>(c.mode),
6387 static_cast<GLint>(c.first),
6388 static_cast<GLsizei>(c.count),
6389 static_cast<GLsizei>(c.primcount));
6392 error::Error GLES2DecoderImpl::DoDrawElements(
6393 const char* function_name,
6399 GLsizei primcount) {
6400 error::Error error = WillAccessBoundFramebufferForDraw();
6401 if (error != error::kNoError)
6403 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6405 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6406 return error::kNoError;
6410 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6411 return error::kNoError;
6414 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6415 return error::kNoError;
6417 if (!validators_->draw_mode.IsValid(mode)) {
6418 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6419 return error::kNoError;
6421 if (!validators_->index_type.IsValid(type)) {
6422 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6423 return error::kNoError;
6425 if (primcount < 0) {
6426 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6427 return error::kNoError;
6430 if (!CheckBoundFramebuffersValid(function_name)) {
6431 return error::kNoError;
6434 if (count == 0 || (instanced && primcount == 0)) {
6435 return error::kNoError;
6438 GLuint max_vertex_accessed;
6439 Buffer* element_array_buffer =
6440 state_.vertex_attrib_manager->element_array_buffer();
6442 if (!element_array_buffer->GetMaxValueForRange(
6443 offset, count, type, &max_vertex_accessed)) {
6445 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6446 return error::kNoError;
6449 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6450 if (!ClearUnclearedTextures()) {
6451 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6452 return error::kNoError;
6454 bool simulated_attrib_0 = false;
6455 if (!SimulateAttrib0(
6456 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6457 return error::kNoError;
6459 bool simulated_fixed_attribs = false;
6460 if (SimulateFixedAttribs(
6461 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6463 bool textures_set = !PrepareTexturesForRender();
6465 // TODO(gman): Refactor to hide these details in BufferManager or
6466 // VertexAttribManager.
6467 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6468 bool used_client_side_array = false;
6469 if (element_array_buffer->IsClientSideArray()) {
6470 used_client_side_array = true;
6471 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6472 indices = element_array_buffer->GetRange(offset, 0);
6476 glDrawElements(mode, count, type, indices);
6478 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6481 if (used_client_side_array) {
6482 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6483 element_array_buffer->service_id());
6486 ProcessPendingQueries();
6488 RestoreStateForTextures();
6490 if (simulated_fixed_attribs) {
6491 RestoreStateForSimulatedFixedAttribs();
6494 if (simulated_attrib_0) {
6495 RestoreStateForAttrib(0);
6498 return error::kNoError;
6501 error::Error GLES2DecoderImpl::HandleDrawElements(
6502 uint32 immediate_data_size, const cmds::DrawElements& c) {
6503 return DoDrawElements("glDrawElements",
6505 static_cast<GLenum>(c.mode),
6506 static_cast<GLsizei>(c.count),
6507 static_cast<GLenum>(c.type),
6508 static_cast<int32>(c.index_offset),
6512 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6513 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6514 if (!features().angle_instanced_arrays) {
6516 GL_INVALID_OPERATION,
6517 "glDrawElementsInstancedANGLE", "function not available");
6518 return error::kNoError;
6520 return DoDrawElements("glDrawElementsInstancedANGLE",
6522 static_cast<GLenum>(c.mode),
6523 static_cast<GLsizei>(c.count),
6524 static_cast<GLenum>(c.type),
6525 static_cast<int32>(c.index_offset),
6526 static_cast<GLsizei>(c.primcount));
6529 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6530 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6531 GLuint max_vertex_accessed = 0;
6532 Buffer* buffer = GetBuffer(buffer_id);
6534 // TODO(gman): Should this be a GL error or a command buffer error?
6536 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6538 if (!buffer->GetMaxValueForRange(
6539 offset, count, type, &max_vertex_accessed)) {
6540 // TODO(gman): Should this be a GL error or a command buffer error?
6542 GL_INVALID_OPERATION,
6543 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6546 return max_vertex_accessed;
6549 // Calls glShaderSource for the various versions of the ShaderSource command.
6550 // Assumes that data / data_size points to a piece of memory that is in range
6551 // of whatever context it came from (shared memory, immediate memory, bucket
6553 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6554 GLuint client_id, const char* data, uint32 data_size) {
6555 std::string str(data, data + data_size);
6556 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6558 return error::kNoError;
6560 // Note: We don't actually call glShaderSource here. We wait until
6561 // the call to glCompileShader.
6562 shader->UpdateSource(str.c_str());
6563 return error::kNoError;
6566 error::Error GLES2DecoderImpl::HandleShaderSource(
6567 uint32 immediate_data_size, const cmds::ShaderSource& c) {
6568 uint32 data_size = c.data_size;
6569 const char* data = GetSharedMemoryAs<const char*>(
6570 c.data_shm_id, c.data_shm_offset, data_size);
6572 return error::kOutOfBounds;
6574 return ShaderSourceHelper(c.shader, data, data_size);
6577 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6578 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6579 Bucket* bucket = GetBucket(c.data_bucket_id);
6580 if (!bucket || bucket->size() == 0) {
6581 return error::kInvalidArguments;
6583 return ShaderSourceHelper(
6584 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6585 bucket->size() - 1);
6588 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6589 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6590 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6594 ShaderTranslator* translator = NULL;
6595 if (use_shader_translator_) {
6596 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6597 vertex_translator_.get() : fragment_translator_.get();
6600 program_manager()->DoCompileShader(shader, translator, feature_info_.get());
6603 void GLES2DecoderImpl::DoGetShaderiv(
6604 GLuint shader_id, GLenum pname, GLint* params) {
6605 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6610 case GL_SHADER_SOURCE_LENGTH:
6611 *params = shader->source() ? shader->source()->size() + 1 : 0;
6613 case GL_COMPILE_STATUS:
6614 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6616 case GL_INFO_LOG_LENGTH:
6617 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6619 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6620 *params = shader->translated_source() ?
6621 shader->translated_source()->size() + 1 : 0;
6626 glGetShaderiv(shader->service_id(), pname, params);
6629 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6630 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6631 GLuint shader_id = c.shader;
6632 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6633 Bucket* bucket = CreateBucket(bucket_id);
6634 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6635 if (!shader || !shader->source()) {
6637 return error::kNoError;
6639 bucket->SetFromString(shader->source()->c_str());
6640 return error::kNoError;
6643 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6644 uint32 immediate_data_size,
6645 const cmds::GetTranslatedShaderSourceANGLE& c) {
6646 GLuint shader_id = c.shader;
6647 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6648 Bucket* bucket = CreateBucket(bucket_id);
6649 Shader* shader = GetShaderInfoNotProgram(
6650 shader_id, "glTranslatedGetShaderSourceANGLE");
6653 return error::kNoError;
6656 bucket->SetFromString(shader->translated_source() ?
6657 shader->translated_source()->c_str() : NULL);
6658 return error::kNoError;
6661 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6662 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6663 GLuint program_id = c.program;
6664 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6665 Bucket* bucket = CreateBucket(bucket_id);
6666 Program* program = GetProgramInfoNotShader(
6667 program_id, "glGetProgramInfoLog");
6668 if (!program || !program->log_info()) {
6669 bucket->SetFromString("");
6670 return error::kNoError;
6672 bucket->SetFromString(program->log_info()->c_str());
6673 return error::kNoError;
6676 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6677 uint32 immediate_data_size, const cmds::GetShaderInfoLog& 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, "glGetShaderInfoLog");
6682 if (!shader || !shader->log_info()) {
6683 bucket->SetFromString("");
6684 return error::kNoError;
6686 bucket->SetFromString(shader->log_info()->c_str());
6687 return error::kNoError;
6690 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6691 return state_.GetEnabled(cap);
6694 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6695 const Buffer* buffer = GetBuffer(client_id);
6696 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6699 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6700 const Framebuffer* framebuffer =
6701 GetFramebuffer(client_id);
6702 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6705 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6706 // IsProgram is true for programs as soon as they are created, until they are
6707 // deleted and no longer in use.
6708 const Program* program = GetProgram(client_id);
6709 return program != NULL && !program->IsDeleted();
6712 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6713 const Renderbuffer* renderbuffer =
6714 GetRenderbuffer(client_id);
6715 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6718 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6719 // IsShader is true for shaders as soon as they are created, until they
6720 // are deleted and not attached to any programs.
6721 const Shader* shader = GetShader(client_id);
6722 return shader != NULL && !shader->IsDeleted();
6725 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6726 const TextureRef* texture_ref = GetTexture(client_id);
6727 return texture_ref && texture_ref->texture()->IsValid();
6730 void GLES2DecoderImpl::DoAttachShader(
6731 GLuint program_client_id, GLint shader_client_id) {
6732 Program* program = GetProgramInfoNotShader(
6733 program_client_id, "glAttachShader");
6737 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6741 if (!program->AttachShader(shader_manager(), shader)) {
6743 GL_INVALID_OPERATION,
6745 "can not attach more than one shader of the same type.");
6748 glAttachShader(program->service_id(), shader->service_id());
6751 void GLES2DecoderImpl::DoDetachShader(
6752 GLuint program_client_id, GLint shader_client_id) {
6753 Program* program = GetProgramInfoNotShader(
6754 program_client_id, "glDetachShader");
6758 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6762 if (!program->DetachShader(shader_manager(), shader)) {
6764 GL_INVALID_OPERATION,
6765 "glDetachShader", "shader not attached to program");
6768 glDetachShader(program->service_id(), shader->service_id());
6771 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6772 Program* program = GetProgramInfoNotShader(
6773 program_client_id, "glValidateProgram");
6777 program->Validate();
6780 void GLES2DecoderImpl::GetVertexAttribHelper(
6781 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6783 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6784 Buffer* buffer = attrib->buffer();
6785 if (buffer && !buffer->IsDeleted()) {
6787 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6788 *params = client_id;
6792 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6793 *params = attrib->enabled();
6795 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6796 *params = attrib->size();
6798 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6799 *params = attrib->gl_stride();
6801 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6802 *params = attrib->type();
6804 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6805 *params = attrib->normalized();
6807 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6808 *params = attrib->divisor();
6816 void GLES2DecoderImpl::DoGetVertexAttribfv(
6817 GLuint index, GLenum pname, GLfloat* params) {
6818 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6821 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6825 case GL_CURRENT_VERTEX_ATTRIB: {
6826 const Vec4& value = state_.attrib_values[index];
6827 params[0] = value.v[0];
6828 params[1] = value.v[1];
6829 params[2] = value.v[2];
6830 params[3] = value.v[3];
6835 GetVertexAttribHelper(attrib, pname, &value);
6836 *params = static_cast<GLfloat>(value);
6842 void GLES2DecoderImpl::DoGetVertexAttribiv(
6843 GLuint index, GLenum pname, GLint* params) {
6844 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6847 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6851 case GL_CURRENT_VERTEX_ATTRIB: {
6852 const Vec4& value = state_.attrib_values[index];
6853 params[0] = static_cast<GLint>(value.v[0]);
6854 params[1] = static_cast<GLint>(value.v[1]);
6855 params[2] = static_cast<GLint>(value.v[2]);
6856 params[3] = static_cast<GLint>(value.v[3]);
6860 GetVertexAttribHelper(attrib, pname, params);
6865 bool GLES2DecoderImpl::SetVertexAttribValue(
6866 const char* function_name, GLuint index, const GLfloat* value) {
6867 if (index >= state_.attrib_values.size()) {
6868 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
6871 Vec4& v = state_.attrib_values[index];
6879 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6880 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6881 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6882 glVertexAttrib1f(index, v0);
6886 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
6887 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6888 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6889 glVertexAttrib2f(index, v0, v1);
6893 void GLES2DecoderImpl::DoVertexAttrib3f(
6894 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
6895 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6896 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6897 glVertexAttrib3f(index, v0, v1, v2);
6901 void GLES2DecoderImpl::DoVertexAttrib4f(
6902 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
6903 GLfloat v[4] = { v0, v1, v2, v3, };
6904 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6905 glVertexAttrib4f(index, v0, v1, v2, v3);
6909 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
6910 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6911 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6912 glVertexAttrib1fv(index, v);
6916 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
6917 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6918 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6919 glVertexAttrib2fv(index, v);
6923 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
6924 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6925 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6926 glVertexAttrib3fv(index, v);
6930 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
6931 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6932 glVertexAttrib4fv(index, v);
6936 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
6937 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
6939 if (!state_.bound_array_buffer.get() ||
6940 state_.bound_array_buffer->IsDeleted()) {
6941 if (state_.vertex_attrib_manager.get() ==
6942 default_vertex_attrib_manager_.get()) {
6944 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
6945 return error::kNoError;
6946 } else if (c.offset != 0) {
6949 "glVertexAttribPointer", "client side arrays are not allowed");
6950 return error::kNoError;
6954 GLuint indx = c.indx;
6955 GLint size = c.size;
6956 GLenum type = c.type;
6957 GLboolean normalized = c.normalized;
6958 GLsizei stride = c.stride;
6959 GLsizei offset = c.offset;
6960 const void* ptr = reinterpret_cast<const void*>(offset);
6961 if (!validators_->vertex_attrib_type.IsValid(type)) {
6962 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
6963 return error::kNoError;
6965 if (!validators_->vertex_attrib_size.IsValid(size)) {
6967 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
6968 return error::kNoError;
6970 if (indx >= group_->max_vertex_attribs()) {
6972 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
6973 return error::kNoError;
6977 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
6978 return error::kNoError;
6982 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
6983 return error::kNoError;
6987 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
6988 return error::kNoError;
6990 GLsizei component_size =
6991 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
6992 if (offset % component_size > 0) {
6994 GL_INVALID_OPERATION,
6995 "glVertexAttribPointer", "offset not valid for type");
6996 return error::kNoError;
6998 if (stride % component_size > 0) {
7000 GL_INVALID_OPERATION,
7001 "glVertexAttribPointer", "stride not valid for type");
7002 return error::kNoError;
7004 state_.vertex_attrib_manager
7005 ->SetAttribInfo(indx,
7006 state_.bound_array_buffer.get(),
7011 stride != 0 ? stride : component_size * size,
7013 if (type != GL_FIXED) {
7014 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7016 return error::kNoError;
7019 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7021 state_.viewport_x = x;
7022 state_.viewport_y = y;
7023 state_.viewport_width = std::min(width, viewport_max_width_);
7024 state_.viewport_height = std::min(height, viewport_max_height_);
7025 glViewport(x, y, width, height);
7028 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7029 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7030 if (!features().angle_instanced_arrays) {
7032 GL_INVALID_OPERATION,
7033 "glVertexAttribDivisorANGLE", "function not available");
7035 GLuint index = c.index;
7036 GLuint divisor = c.divisor;
7037 if (index >= group_->max_vertex_attribs()) {
7040 "glVertexAttribDivisorANGLE", "index out of range");
7041 return error::kNoError;
7044 state_.vertex_attrib_manager->SetDivisor(
7047 glVertexAttribDivisorANGLE(index, divisor);
7048 return error::kNoError;
7051 template <typename pixel_data_type>
7052 static void WriteAlphaData(
7053 void *pixels, uint32 row_count, uint32 channel_count,
7054 uint32 alpha_channel_index, uint32 unpadded_row_size,
7055 uint32 padded_row_size, pixel_data_type alpha_value) {
7056 DCHECK_GT(channel_count, 0U);
7057 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7058 uint32 unpadded_row_size_in_elements =
7059 unpadded_row_size / sizeof(pixel_data_type);
7060 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7061 uint32 padded_row_size_in_elements =
7062 padded_row_size / sizeof(pixel_data_type);
7063 pixel_data_type* dst =
7064 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7065 for (uint32 yy = 0; yy < row_count; ++yy) {
7066 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7067 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7070 dst += padded_row_size_in_elements;
7074 void GLES2DecoderImpl::FinishReadPixels(
7075 const cmds::ReadPixels& c,
7077 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7078 GLsizei width = c.width;
7079 GLsizei height = c.height;
7080 GLenum format = c.format;
7081 GLenum type = c.type;
7082 typedef cmds::ReadPixels::Result Result;
7084 Result* result = NULL;
7085 if (c.result_shm_id != 0) {
7086 result = GetSharedMemoryAs<Result*>(
7087 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7090 glDeleteBuffersARB(1, &buffer);
7095 GLES2Util::ComputeImageDataSizes(
7096 width, height, format, type, state_.pack_alignment, &pixels_size,
7098 void* pixels = GetSharedMemoryAs<void*>(
7099 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7102 glDeleteBuffersARB(1, &buffer);
7108 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7110 if (features().map_buffer_range) {
7111 data = glMapBufferRange(
7112 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7114 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7116 memcpy(pixels, data, pixels_size);
7117 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7118 // have to restore the state.
7119 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7120 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7121 glDeleteBuffersARB(1, &buffer);
7124 if (result != NULL) {
7128 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7129 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7130 if ((channels_exist & 0x0008) == 0 &&
7131 workarounds().clear_alpha_in_readpixels) {
7132 // Set the alpha to 255 because some drivers are buggy in this regard.
7135 uint32 unpadded_row_size;
7136 uint32 padded_row_size;
7137 if (!GLES2Util::ComputeImageDataSizes(
7138 width, 2, format, type, state_.pack_alignment, &temp_size,
7139 &unpadded_row_size, &padded_row_size)) {
7143 uint32 channel_count = 0;
7144 uint32 alpha_channel = 0;
7157 if (channel_count > 0) {
7159 case GL_UNSIGNED_BYTE:
7160 WriteAlphaData<uint8>(
7161 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7162 padded_row_size, 0xFF);
7165 WriteAlphaData<float>(
7166 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7167 padded_row_size, 1.0f);
7170 WriteAlphaData<uint16>(
7171 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7172 padded_row_size, 0x3C00);
7180 error::Error GLES2DecoderImpl::HandleReadPixels(
7181 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7182 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7183 if (fbo_error != error::kNoError)
7187 GLsizei width = c.width;
7188 GLsizei height = c.height;
7189 GLenum format = c.format;
7190 GLenum type = c.type;
7191 GLboolean async = c.async;
7192 if (width < 0 || height < 0) {
7193 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7194 return error::kNoError;
7196 typedef cmds::ReadPixels::Result Result;
7198 if (!GLES2Util::ComputeImageDataSizes(
7199 width, height, format, type, state_.pack_alignment, &pixels_size,
7201 return error::kOutOfBounds;
7203 void* pixels = GetSharedMemoryAs<void*>(
7204 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7206 return error::kOutOfBounds;
7208 Result* result = NULL;
7209 if (c.result_shm_id != 0) {
7210 result = GetSharedMemoryAs<Result*>(
7211 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7213 return error::kOutOfBounds;
7217 if (!validators_->read_pixel_format.IsValid(format)) {
7218 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7219 return error::kNoError;
7221 if (!validators_->read_pixel_type.IsValid(type)) {
7222 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7223 return error::kNoError;
7225 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7226 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7227 // format and type are acceptable enums but not guaranteed to be supported
7228 // for this framebuffer. Have to ask gl if they are valid.
7229 GLint preferred_format = 0;
7230 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7231 GLint preferred_type = 0;
7232 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7233 if (format != static_cast<GLenum>(preferred_format) ||
7234 type != static_cast<GLenum>(preferred_type)) {
7236 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7237 "with the current read framebuffer");
7238 return error::kNoError;
7241 if (width == 0 || height == 0) {
7242 return error::kNoError;
7245 // Get the size of the current fbo or backbuffer.
7246 gfx::Size max_size = GetBoundReadFrameBufferSize();
7250 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7252 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7253 return error::kNoError;
7256 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7257 return error::kNoError;
7260 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
7262 ScopedResolvedFrameBufferBinder binder(this, false, true);
7264 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7265 // The user requested an out of range area. Get the results 1 line
7268 uint32 unpadded_row_size;
7269 uint32 padded_row_size;
7270 if (!GLES2Util::ComputeImageDataSizes(
7271 width, 2, format, type, state_.pack_alignment, &temp_size,
7272 &unpadded_row_size, &padded_row_size)) {
7274 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7275 return error::kNoError;
7278 GLint dest_x_offset = std::max(-x, 0);
7279 uint32 dest_row_offset;
7280 if (!GLES2Util::ComputeImageDataSizes(
7281 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7284 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7285 return error::kNoError;
7288 // Copy each row into the larger dest rect.
7289 int8* dst = static_cast<int8*>(pixels);
7290 GLint read_x = std::max(0, x);
7291 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7292 GLint read_width = read_end_x - read_x;
7293 for (GLint yy = 0; yy < height; ++yy) {
7297 memset(dst, 0, unpadded_row_size);
7299 // If the row is in range, copy it.
7300 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7302 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7304 dst += padded_row_size;
7307 if (async && features().use_async_readpixels) {
7309 glGenBuffersARB(1, &buffer);
7310 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7311 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7312 GLenum error = glGetError();
7313 if (error == GL_NO_ERROR) {
7314 glReadPixels(x, y, width, height, format, type, 0);
7315 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7316 new FenceCallback()));
7317 WaitForReadPixels(base::Bind(
7318 &GLES2DecoderImpl::FinishReadPixels,
7319 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7320 <GLES2DecoderImpl>(this),
7322 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7323 return error::kNoError;
7326 glReadPixels(x, y, width, height, format, type, pixels);
7328 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7329 if (error == GL_NO_ERROR) {
7330 if (result != NULL) {
7333 FinishReadPixels(c, 0);
7336 return error::kNoError;
7339 error::Error GLES2DecoderImpl::HandlePixelStorei(
7340 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7341 GLenum pname = c.pname;
7342 GLenum param = c.param;
7343 if (!validators_->pixel_store.IsValid(pname)) {
7344 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7345 return error::kNoError;
7348 case GL_PACK_ALIGNMENT:
7349 case GL_UNPACK_ALIGNMENT:
7350 if (!validators_->pixel_store_alignment.IsValid(param)) {
7352 GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
7353 return error::kNoError;
7356 case GL_UNPACK_FLIP_Y_CHROMIUM:
7357 unpack_flip_y_ = (param != 0);
7358 return error::kNoError;
7359 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7360 unpack_premultiply_alpha_ = (param != 0);
7361 return error::kNoError;
7362 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7363 unpack_unpremultiply_alpha_ = (param != 0);
7364 return error::kNoError;
7368 glPixelStorei(pname, param);
7370 case GL_PACK_ALIGNMENT:
7371 state_.pack_alignment = param;
7373 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7374 state_.pack_reverse_row_order = (param != 0);
7376 case GL_UNPACK_ALIGNMENT:
7377 state_.unpack_alignment = param;
7380 // Validation should have prevented us from getting here.
7384 return error::kNoError;
7387 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7388 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7389 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7390 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
7392 GL_INVALID_OPERATION,
7393 "glPostSubBufferCHROMIUM", "command not supported by surface");
7394 return error::kNoError;
7397 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7400 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7401 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7402 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7403 is_offscreen ? offscreen_size_ : surface_->GetSize());
7405 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7406 return error::kNoError;
7408 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7409 return error::kLostContext;
7413 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7414 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7415 const std::string& name_str) {
7416 if (!StringIsValidForGLES(name_str.c_str())) {
7418 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7419 return error::kNoError;
7421 Program* program = GetProgramInfoNotShader(
7422 client_id, "glGetAttribLocation");
7424 return error::kNoError;
7426 if (!program->IsValid()) {
7428 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7429 return error::kNoError;
7431 GLint* location = GetSharedMemoryAs<GLint*>(
7432 location_shm_id, location_shm_offset, sizeof(GLint));
7434 return error::kOutOfBounds;
7436 // Require the client to init this incase the context is lost and we are no
7437 // longer executing commands.
7438 if (*location != -1) {
7439 return error::kGenericError;
7441 *location = program->GetAttribLocation(name_str);
7442 return error::kNoError;
7445 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7446 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7447 uint32 name_size = c.data_size;
7448 const char* name = GetSharedMemoryAs<const char*>(
7449 c.name_shm_id, c.name_shm_offset, name_size);
7451 return error::kOutOfBounds;
7453 String name_str(name, name_size);
7454 return GetAttribLocationHelper(
7455 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7458 error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
7459 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
7460 Bucket* bucket = GetBucket(c.name_bucket_id);
7462 return error::kInvalidArguments;
7464 std::string name_str;
7465 if (!bucket->GetAsString(&name_str)) {
7466 return error::kInvalidArguments;
7468 return GetAttribLocationHelper(
7469 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7472 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7473 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7474 const std::string& name_str) {
7475 if (!StringIsValidForGLES(name_str.c_str())) {
7477 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7478 return error::kNoError;
7480 Program* program = GetProgramInfoNotShader(
7481 client_id, "glUniformLocation");
7483 return error::kNoError;
7485 if (!program->IsValid()) {
7487 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7488 return error::kNoError;
7490 GLint* location = GetSharedMemoryAs<GLint*>(
7491 location_shm_id, location_shm_offset, sizeof(GLint));
7493 return error::kOutOfBounds;
7495 // Require the client to init this incase the context is lost an we are no
7496 // longer executing commands.
7497 if (*location != -1) {
7498 return error::kGenericError;
7500 *location = program->GetUniformFakeLocation(name_str);
7501 return error::kNoError;
7504 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7505 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7506 uint32 name_size = c.data_size;
7507 const char* name = GetSharedMemoryAs<const char*>(
7508 c.name_shm_id, c.name_shm_offset, name_size);
7510 return error::kOutOfBounds;
7512 String name_str(name, name_size);
7513 return GetUniformLocationHelper(
7514 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7517 error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
7518 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
7519 Bucket* bucket = GetBucket(c.name_bucket_id);
7521 return error::kInvalidArguments;
7523 std::string name_str;
7524 if (!bucket->GetAsString(&name_str)) {
7525 return error::kInvalidArguments;
7527 return GetUniformLocationHelper(
7528 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7531 error::Error GLES2DecoderImpl::HandleGetString(
7532 uint32 immediate_data_size, const cmds::GetString& c) {
7533 GLenum name = static_cast<GLenum>(c.name);
7534 if (!validators_->string_type.IsValid(name)) {
7535 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7536 return error::kNoError;
7538 const char* str = reinterpret_cast<const char*>(glGetString(name));
7539 std::string extensions;
7542 str = "OpenGL ES 2.0 Chromium";
7544 case GL_SHADING_LANGUAGE_VERSION:
7545 str = "OpenGL ES GLSL ES 1.0 Chromium";
7549 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7550 // They are used by WEBGL_debug_renderer_info.
7551 if (!force_webgl_glsl_validation_)
7556 // For WebGL contexts, strip out the OES derivatives and
7557 // EXT frag depth extensions if they have not been enabled.
7558 if (force_webgl_glsl_validation_) {
7559 extensions = feature_info_->extensions();
7560 if (!derivatives_explicitly_enabled_) {
7561 size_t offset = extensions.find(kOESDerivativeExtension);
7562 if (std::string::npos != offset) {
7563 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7567 if (!frag_depth_explicitly_enabled_) {
7568 size_t offset = extensions.find(kEXTFragDepthExtension);
7569 if (std::string::npos != offset) {
7570 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7574 if (!draw_buffers_explicitly_enabled_) {
7575 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7576 if (std::string::npos != offset) {
7577 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7582 extensions = feature_info_->extensions().c_str();
7584 std::string surface_extensions = surface_->GetExtensions();
7585 if (!surface_extensions.empty())
7586 extensions += " " + surface_extensions;
7587 str = extensions.c_str();
7593 Bucket* bucket = CreateBucket(c.bucket_id);
7594 bucket->SetFromString(str);
7595 return error::kNoError;
7598 error::Error GLES2DecoderImpl::HandleBufferData(
7599 uint32 immediate_data_size, const cmds::BufferData& c) {
7600 GLenum target = static_cast<GLenum>(c.target);
7601 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7602 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7603 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7604 GLenum usage = static_cast<GLenum>(c.usage);
7605 const void* data = NULL;
7606 if (data_shm_id != 0 || data_shm_offset != 0) {
7607 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7609 return error::kOutOfBounds;
7612 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7613 return error::kNoError;
7616 void GLES2DecoderImpl::DoBufferSubData(
7617 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7618 // Just delegate it. Some validation is actually done before this.
7619 buffer_manager()->ValidateAndDoBufferSubData(
7620 &state_, target, offset, size, data);
7623 bool GLES2DecoderImpl::ClearLevel(
7624 unsigned service_id,
7625 unsigned bind_target,
7632 bool is_texture_immutable) {
7633 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7634 if (feature_info_->feature_flags().angle_depth_texture &&
7635 (channels & GLES2Util::kDepth) != 0) {
7636 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7637 // on depth formats.
7639 glGenFramebuffersEXT(1, &fb);
7640 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7642 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7643 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7644 GL_DEPTH_ATTACHMENT;
7646 glFramebufferTexture2DEXT(
7647 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7648 // ANGLE promises a depth only attachment ok.
7649 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7650 GL_FRAMEBUFFER_COMPLETE) {
7657 glDisable(GL_SCISSOR_TEST);
7658 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7660 RestoreClearState();
7662 glDeleteFramebuffersEXT(1, &fb);
7663 Framebuffer* framebuffer =
7664 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7665 GLuint fb_service_id =
7666 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7667 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7671 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7674 uint32 padded_row_size;
7675 if (!GLES2Util::ComputeImageDataSizes(
7676 width, height, format, type, state_.unpack_alignment, &size,
7677 NULL, &padded_row_size)) {
7681 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7685 if (size > kMaxZeroSize) {
7686 if (kMaxZeroSize < padded_row_size) {
7687 // That'd be an awfully large texture.
7690 // We should never have a large total size with a zero row size.
7691 DCHECK_GT(padded_row_size, 0U);
7692 tile_height = kMaxZeroSize / padded_row_size;
7693 if (!GLES2Util::ComputeImageDataSizes(
7694 width, tile_height, format, type, state_.unpack_alignment, &size,
7699 tile_height = height;
7702 // Assumes the size has already been checked.
7703 scoped_ptr<char[]> zero(new char[size]);
7704 memset(zero.get(), 0, size);
7705 glBindTexture(bind_target, service_id);
7708 while (y < height) {
7709 GLint h = y + tile_height > height ? height - y : tile_height;
7710 if (is_texture_immutable || h != height) {
7711 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7714 target, level, format, width, h, 0, format, type, zero.get());
7718 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7719 &state_, bind_target);
7720 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7726 const int kS3TCBlockWidth = 4;
7727 const int kS3TCBlockHeight = 4;
7728 const int kS3TCDXT1BlockSize = 8;
7729 const int kS3TCDXT3AndDXT5BlockSize = 16;
7730 const int kETC1BlockWidth = 4;
7731 const int kETC1BlockHeight = 4;
7732 const int kETC1BlockSize = 8;
7734 bool IsValidDXTSize(GLint level, GLsizei size) {
7735 return (size == 1) ||
7736 (size == 2) || !(size % kS3TCBlockWidth);
7739 } // anonymous namespace.
7741 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7742 const char* function_name,
7743 GLsizei width, GLsizei height, GLenum format, size_t size) {
7744 unsigned int bytes_required = 0;
7747 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7748 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7749 int num_blocks_across =
7750 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7751 int num_blocks_down =
7752 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7753 int num_blocks = num_blocks_across * num_blocks_down;
7754 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7757 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7758 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7759 int num_blocks_across =
7760 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7761 int num_blocks_down =
7762 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7763 int num_blocks = num_blocks_across * num_blocks_down;
7764 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7767 case GL_ETC1_RGB8_OES: {
7768 int num_blocks_across =
7769 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7770 int num_blocks_down =
7771 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7772 int num_blocks = num_blocks_across * num_blocks_down;
7773 bytes_required = num_blocks * kETC1BlockSize;
7777 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7781 if (size != bytes_required) {
7783 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7790 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7791 const char* function_name,
7792 GLint level, GLsizei width, GLsizei height, GLenum format) {
7794 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7795 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7796 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7797 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7798 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7800 GL_INVALID_OPERATION, function_name,
7801 "width or height invalid for level");
7806 case GL_ETC1_RGB8_OES:
7807 if (width <= 0 || height <= 0) {
7809 GL_INVALID_OPERATION, function_name,
7810 "width or height invalid for level");
7819 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7820 const char* function_name,
7821 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7822 GLsizei width, GLsizei height, GLenum format,
7824 if (xoffset < 0 || yoffset < 0) {
7826 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7831 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7832 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7833 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7834 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7835 const int kBlockWidth = 4;
7836 const int kBlockHeight = 4;
7837 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7839 GL_INVALID_OPERATION, function_name,
7840 "xoffset or yoffset not multiple of 4");
7843 GLsizei tex_width = 0;
7844 GLsizei tex_height = 0;
7845 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7846 width - xoffset > tex_width ||
7847 height - yoffset > tex_height) {
7849 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7852 return ValidateCompressedTexDimensions(
7853 function_name, level, width, height, format);
7855 case GL_ETC1_RGB8_OES: {
7857 GL_INVALID_OPERATION, function_name,
7858 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7866 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7869 GLenum internal_format,
7875 // TODO(gman): Validate image_size is correct for width, height and format.
7876 if (!validators_->texture_target.IsValid(target)) {
7877 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7878 "glCompressedTexImage2D", target, "target");
7879 return error::kNoError;
7881 if (!validators_->compressed_texture_format.IsValid(
7883 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7884 "glCompressedTexImage2D", internal_format, "internal_format");
7885 return error::kNoError;
7887 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7891 "glCompressedTexImage2D", "dimensions out of range");
7892 return error::kNoError;
7894 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7899 "glCompressedTexImage2D", "unknown texture target");
7900 return error::kNoError;
7902 Texture* texture = texture_ref->texture();
7903 if (texture->IsImmutable()) {
7905 GL_INVALID_OPERATION,
7906 "glCompressedTexImage2D", "texture is immutable");
7907 return error::kNoError;
7910 if (!ValidateCompressedTexDimensions(
7911 "glCompressedTexImage2D", level, width, height, internal_format) ||
7912 !ValidateCompressedTexFuncData(
7913 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
7914 return error::kNoError;
7917 if (!EnsureGPUMemoryAvailable(image_size)) {
7919 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
7920 return error::kNoError;
7923 if (texture->IsAttachedToFramebuffer()) {
7924 framebuffer_state_.clear_state_dirty = true;
7927 scoped_ptr<int8[]> zero;
7929 zero.reset(new int8[image_size]);
7930 memset(zero.get(), 0, image_size);
7933 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
7934 glCompressedTexImage2D(
7935 target, level, internal_format, width, height, border, image_size, data);
7936 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
7937 if (error == GL_NO_ERROR) {
7938 texture_manager()->SetLevelInfo(
7939 texture_ref, target, level, internal_format,
7940 width, height, 1, border, 0, 0, true);
7942 return error::kNoError;
7945 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
7946 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
7947 GLenum target = static_cast<GLenum>(c.target);
7948 GLint level = static_cast<GLint>(c.level);
7949 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7950 GLsizei width = static_cast<GLsizei>(c.width);
7951 GLsizei height = static_cast<GLsizei>(c.height);
7952 GLint border = static_cast<GLint>(c.border);
7953 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7954 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7955 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7956 const void* data = NULL;
7957 if (data_shm_id != 0 || data_shm_offset != 0) {
7958 data = GetSharedMemoryAs<const void*>(
7959 data_shm_id, data_shm_offset, image_size);
7961 return error::kOutOfBounds;
7964 return DoCompressedTexImage2D(
7965 target, level, internal_format, width, height, border, image_size, data);
7968 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
7969 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
7970 GLenum target = static_cast<GLenum>(c.target);
7971 GLint level = static_cast<GLint>(c.level);
7972 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7973 GLsizei width = static_cast<GLsizei>(c.width);
7974 GLsizei height = static_cast<GLsizei>(c.height);
7975 GLint border = static_cast<GLint>(c.border);
7976 Bucket* bucket = GetBucket(c.bucket_id);
7978 return error::kInvalidArguments;
7980 uint32 data_size = bucket->size();
7981 GLsizei imageSize = data_size;
7982 const void* data = bucket->GetData(0, data_size);
7984 return error::kInvalidArguments;
7986 return DoCompressedTexImage2D(
7987 target, level, internal_format, width, height, border,
7991 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7992 uint32 immediate_data_size,
7993 const cmds::CompressedTexSubImage2DBucket& c) {
7994 GLenum target = static_cast<GLenum>(c.target);
7995 GLint level = static_cast<GLint>(c.level);
7996 GLint xoffset = static_cast<GLint>(c.xoffset);
7997 GLint yoffset = static_cast<GLint>(c.yoffset);
7998 GLsizei width = static_cast<GLsizei>(c.width);
7999 GLsizei height = static_cast<GLsizei>(c.height);
8000 GLenum format = static_cast<GLenum>(c.format);
8001 Bucket* bucket = GetBucket(c.bucket_id);
8003 return error::kInvalidArguments;
8005 uint32 data_size = bucket->size();
8006 GLsizei imageSize = data_size;
8007 const void* data = bucket->GetData(0, data_size);
8009 return error::kInvalidArguments;
8011 if (!validators_->texture_target.IsValid(target)) {
8013 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8014 return error::kNoError;
8016 if (!validators_->compressed_texture_format.IsValid(format)) {
8017 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8018 "glCompressedTexSubImage2D", format, "format");
8019 return error::kNoError;
8023 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8024 return error::kNoError;
8028 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8029 return error::kNoError;
8031 if (imageSize < 0) {
8033 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8034 return error::kNoError;
8036 DoCompressedTexSubImage2D(
8037 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8038 return error::kNoError;
8041 error::Error GLES2DecoderImpl::HandleTexImage2D(
8042 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8043 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
8044 // Set as failed for now, but if it successed, this will be set to not failed.
8045 texture_state_.tex_image_2d_failed = true;
8046 GLenum target = static_cast<GLenum>(c.target);
8047 GLint level = static_cast<GLint>(c.level);
8048 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8049 // for internalformat.
8050 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8051 GLsizei width = static_cast<GLsizei>(c.width);
8052 GLsizei height = static_cast<GLsizei>(c.height);
8053 GLint border = static_cast<GLint>(c.border);
8054 GLenum format = static_cast<GLenum>(c.format);
8055 GLenum type = static_cast<GLenum>(c.type);
8056 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8057 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8059 if (!GLES2Util::ComputeImageDataSizes(
8060 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8062 return error::kOutOfBounds;
8064 const void* pixels = NULL;
8065 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8066 pixels = GetSharedMemoryAs<const void*>(
8067 pixels_shm_id, pixels_shm_offset, pixels_size);
8069 return error::kOutOfBounds;
8073 TextureManager::DoTextImage2DArguments args = {
8074 target, level, internal_format, width, height, border, format, type,
8075 pixels, pixels_size};
8076 texture_manager()->ValidateAndDoTexImage2D(
8077 &texture_state_, &state_, &framebuffer_state_, args);
8078 return error::kNoError;
8081 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8090 const void * data) {
8091 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8095 GL_INVALID_OPERATION,
8096 "glCompressedTexSubImage2D", "unknown texture for target");
8099 Texture* texture = texture_ref->texture();
8101 GLenum internal_format = 0;
8102 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8104 GL_INVALID_OPERATION,
8105 "glCompressedTexSubImage2D", "level does not exist.");
8108 if (internal_format != format) {
8110 GL_INVALID_OPERATION,
8111 "glCompressedTexSubImage2D", "format does not match internal format.");
8114 if (!texture->ValidForTexture(
8115 target, level, xoffset, yoffset, width, height, format, type)) {
8117 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8121 if (!ValidateCompressedTexFuncData(
8122 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8123 !ValidateCompressedTexSubDimensions(
8124 "glCompressedTexSubImage2D",
8125 target, level, xoffset, yoffset, width, height, format, texture)) {
8130 // Note: There is no need to deal with texture cleared tracking here
8131 // because the validation above means you can only get here if the level
8132 // is already a matching compressed format and in that case
8133 // CompressedTexImage2D already cleared the texture.
8134 glCompressedTexSubImage2D(
8135 target, level, xoffset, yoffset, width, height, format, image_size, data);
8139 GLint start, GLint range, GLint sourceRange,
8140 GLint* out_start, GLint* out_range) {
8147 GLint end = start + range;
8148 if (end > sourceRange) {
8149 range -= end - sourceRange;
8155 void GLES2DecoderImpl::DoCopyTexImage2D(
8158 GLenum internal_format,
8164 DCHECK(!ShouldDeferReads());
8165 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8169 GL_INVALID_OPERATION,
8170 "glCopyTexImage2D", "unknown texture for target");
8173 Texture* texture = texture_ref->texture();
8174 if (texture->IsImmutable()) {
8176 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8178 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8181 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8184 if (!texture_manager()->ValidateTextureParameters(
8185 state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
8186 GL_UNSIGNED_BYTE, level)) {
8190 // Check we have compatible formats.
8191 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8192 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8193 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8195 if ((channels_needed & channels_exist) != channels_needed) {
8197 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8201 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8203 GL_INVALID_OPERATION,
8204 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8208 uint32 estimated_size = 0;
8209 if (!GLES2Util::ComputeImageDataSizes(
8210 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8211 &estimated_size, NULL, NULL)) {
8213 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8217 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8218 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8222 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8226 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8227 ScopedResolvedFrameBufferBinder binder(this, false, true);
8228 gfx::Size size = GetBoundReadFrameBufferSize();
8230 if (texture->IsAttachedToFramebuffer()) {
8231 framebuffer_state_.clear_state_dirty = true;
8234 // Clip to size to source dimensions
8237 GLint copyWidth = 0;
8238 GLint copyHeight = 0;
8239 Clip(x, width, size.width(), ©X, ©Width);
8240 Clip(y, height, size.height(), ©Y, ©Height);
8244 copyWidth != width ||
8245 copyHeight != height) {
8246 // some part was clipped so clear the texture.
8248 texture->service_id(), texture->target(),
8249 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
8250 texture->IsImmutable())) {
8252 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8255 if (copyHeight > 0 && copyWidth > 0) {
8256 GLint dx = copyX - x;
8257 GLint dy = copyY - y;
8260 glCopyTexSubImage2D(target, level,
8261 destX, destY, copyX, copyY,
8262 copyWidth, copyHeight);
8265 glCopyTexImage2D(target, level, internal_format,
8266 copyX, copyY, copyWidth, copyHeight, border);
8268 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8269 if (error == GL_NO_ERROR) {
8270 texture_manager()->SetLevelInfo(
8271 texture_ref, target, level, internal_format, width, height, 1,
8272 border, internal_format, GL_UNSIGNED_BYTE, true);
8276 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8285 DCHECK(!ShouldDeferReads());
8286 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8290 GL_INVALID_OPERATION,
8291 "glCopyTexSubImage2D", "unknown texture for target");
8294 Texture* texture = texture_ref->texture();
8297 if (!texture->GetLevelType(target, level, &type, &format) ||
8298 !texture->ValidForTexture(
8299 target, level, xoffset, yoffset, width, height, format, type)) {
8301 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8304 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8306 GL_INVALID_OPERATION,
8307 "glCopyTexSubImage2D", "async upload pending for texture");
8311 // Check we have compatible formats.
8312 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8313 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8314 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8316 if (!channels_needed ||
8317 (channels_needed & channels_exist) != channels_needed) {
8319 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8323 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8325 GL_INVALID_OPERATION,
8326 "glCopySubImage2D", "can not be used with depth or stencil textures");
8330 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8334 ScopedResolvedFrameBufferBinder binder(this, false, true);
8335 gfx::Size size = GetBoundReadFrameBufferSize();
8338 GLint copyWidth = 0;
8339 GLint copyHeight = 0;
8340 Clip(x, width, size.width(), ©X, ©Width);
8341 Clip(y, height, size.height(), ©Y, ©Height);
8343 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8345 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8351 copyWidth != width ||
8352 copyHeight != height) {
8353 // some part was clipped so clear the sub rect.
8354 uint32 pixels_size = 0;
8355 if (!GLES2Util::ComputeImageDataSizes(
8356 width, height, format, type, state_.unpack_alignment, &pixels_size,
8359 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8362 scoped_ptr<char[]> zero(new char[pixels_size]);
8363 memset(zero.get(), 0, pixels_size);
8365 target, level, xoffset, yoffset, width, height,
8366 format, type, zero.get());
8369 if (copyHeight > 0 && copyWidth > 0) {
8370 GLint dx = copyX - x;
8371 GLint dy = copyY - y;
8372 GLint destX = xoffset + dx;
8373 GLint destY = yoffset + dy;
8374 glCopyTexSubImage2D(target, level,
8375 destX, destY, copyX, copyY,
8376 copyWidth, copyHeight);
8380 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8381 error::Error* error,
8382 const char* function_name,
8391 const void * data) {
8392 (*error) = error::kNoError;
8393 if (!validators_->texture_target.IsValid(target)) {
8394 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8398 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8402 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8405 if (!validators_->texture_format.IsValid(format)) {
8406 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8409 if (!validators_->pixel_type.IsValid(type)) {
8410 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
8413 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8417 GL_INVALID_OPERATION,
8418 function_name, "unknown texture for target");
8421 Texture* texture = texture_ref->texture();
8422 GLenum current_type = 0;
8423 GLenum internal_format = 0;
8424 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
8426 GL_INVALID_OPERATION, function_name, "level does not exist.");
8429 if (format != internal_format) {
8431 GL_INVALID_OPERATION,
8432 function_name, "format does not match internal format.");
8435 if (type != current_type) {
8437 GL_INVALID_OPERATION,
8438 function_name, "type does not match type of texture.");
8441 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8443 GL_INVALID_OPERATION,
8444 function_name, "async upload pending for texture");
8447 if (!texture->ValidForTexture(
8448 target, level, xoffset, yoffset, width, height, format, type)) {
8449 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8452 if ((GLES2Util::GetChannelsForFormat(format) &
8453 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8455 GL_INVALID_OPERATION,
8456 function_name, "can not supply data for depth or stencil textures");
8460 (*error) = error::kOutOfBounds;
8466 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8475 const void * data) {
8476 error::Error error = error::kNoError;
8477 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8478 xoffset, yoffset, width, height, format, type, data)) {
8481 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8483 Texture* texture = texture_ref->texture();
8484 GLsizei tex_width = 0;
8485 GLsizei tex_height = 0;
8486 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8488 if (xoffset != 0 || yoffset != 0 ||
8489 width != tex_width || height != tex_height) {
8490 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8493 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8494 return error::kNoError;
8496 ScopedTextureUploadTimer timer(&texture_state_);
8498 target, level, xoffset, yoffset, width, height, format, type, data);
8499 return error::kNoError;
8502 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8503 !texture->IsImmutable()) {
8504 ScopedTextureUploadTimer timer(&texture_state_);
8505 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8506 // same as internal_foramt. If that changes we'll need to look them up.
8508 target, level, format, width, height, 0, format, type, data);
8510 ScopedTextureUploadTimer timer(&texture_state_);
8512 target, level, xoffset, yoffset, width, height, format, type, data);
8514 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8515 return error::kNoError;
8518 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8519 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8520 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8521 GLboolean internal = static_cast<GLboolean>(c.internal);
8522 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8523 return error::kNoError;
8525 GLenum target = static_cast<GLenum>(c.target);
8526 GLint level = static_cast<GLint>(c.level);
8527 GLint xoffset = static_cast<GLint>(c.xoffset);
8528 GLint yoffset = static_cast<GLint>(c.yoffset);
8529 GLsizei width = static_cast<GLsizei>(c.width);
8530 GLsizei height = static_cast<GLsizei>(c.height);
8531 GLenum format = static_cast<GLenum>(c.format);
8532 GLenum type = static_cast<GLenum>(c.type);
8534 if (!GLES2Util::ComputeImageDataSizes(
8535 width, height, format, type, state_.unpack_alignment, &data_size,
8537 return error::kOutOfBounds;
8539 const void* pixels = GetSharedMemoryAs<const void*>(
8540 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8541 return DoTexSubImage2D(
8542 target, level, xoffset, yoffset, width, height, format, type, pixels);
8545 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8546 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8547 GLuint index = static_cast<GLuint>(c.index);
8548 GLenum pname = static_cast<GLenum>(c.pname);
8549 typedef cmds::GetVertexAttribPointerv::Result Result;
8550 Result* result = GetSharedMemoryAs<Result*>(
8551 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8553 return error::kOutOfBounds;
8555 // Check that the client initialized the result.
8556 if (result->size != 0) {
8557 return error::kInvalidArguments;
8559 if (!validators_->vertex_pointer.IsValid(pname)) {
8560 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8561 "glGetVertexAttribPointerv", pname, "pname");
8562 return error::kNoError;
8564 if (index >= group_->max_vertex_attribs()) {
8566 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8567 return error::kNoError;
8569 result->SetNumResults(1);
8570 *result->GetData() =
8571 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8572 return error::kNoError;
8575 bool GLES2DecoderImpl::GetUniformSetup(
8576 GLuint program_id, GLint fake_location,
8577 uint32 shm_id, uint32 shm_offset,
8578 error::Error* error, GLint* real_location,
8579 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8582 DCHECK(result_pointer);
8583 DCHECK(result_type);
8584 DCHECK(real_location);
8585 *error = error::kNoError;
8586 // Make sure we have enough room for the result on failure.
8587 SizedResult<GLint>* result;
8588 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8589 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8591 *error = error::kOutOfBounds;
8594 *result_pointer = result;
8595 // Set the result size to 0 so the client does not have to check for success.
8596 result->SetNumResults(0);
8597 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8601 if (!program->IsValid()) {
8602 // Program was not linked successfully. (ie, glLinkProgram)
8604 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8607 *service_id = program->service_id();
8608 GLint array_index = -1;
8609 const Program::UniformInfo* uniform_info =
8610 program->GetUniformInfoByFakeLocation(
8611 fake_location, real_location, &array_index);
8612 if (!uniform_info) {
8613 // No such location.
8615 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8618 GLenum type = uniform_info->type;
8619 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8621 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8624 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8625 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8627 *error = error::kOutOfBounds;
8630 result->size = size;
8631 *result_type = type;
8635 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8636 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8637 GLuint program = c.program;
8638 GLint fake_location = c.location;
8641 GLint real_location = -1;
8644 if (GetUniformSetup(
8645 program, fake_location, c.params_shm_id, c.params_shm_offset,
8646 &error, &real_location, &service_id, &result, &result_type)) {
8648 service_id, real_location,
8649 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8654 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8655 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8656 GLuint program = c.program;
8657 GLint fake_location = c.location;
8659 GLint real_location = -1;
8661 typedef cmds::GetUniformfv::Result Result;
8664 if (GetUniformSetup(
8665 program, fake_location, c.params_shm_id, c.params_shm_offset,
8666 &error, &real_location, &service_id,
8667 reinterpret_cast<void**>(&result), &result_type)) {
8668 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8669 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8670 GLsizei num_values = result->GetNumResults();
8671 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8672 glGetUniformiv(service_id, real_location, temp.get());
8673 GLfloat* dst = result->GetData();
8674 for (GLsizei ii = 0; ii < num_values; ++ii) {
8675 dst[ii] = (temp[ii] != 0);
8678 glGetUniformfv(service_id, real_location, result->GetData());
8684 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8685 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8686 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8687 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8688 typedef cmds::GetShaderPrecisionFormat::Result Result;
8689 Result* result = GetSharedMemoryAs<Result*>(
8690 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8692 return error::kOutOfBounds;
8694 // Check that the client initialized the result.
8695 if (result->success != 0) {
8696 return error::kInvalidArguments;
8698 if (!validators_->shader_type.IsValid(shader_type)) {
8699 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8700 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8701 return error::kNoError;
8703 if (!validators_->shader_precision.IsValid(precision_type)) {
8704 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8705 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8706 return error::kNoError;
8709 result->success = 1; // true
8711 GLint range[2] = { 0, 0 };
8712 GLint precision = 0;
8713 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8715 result->min_range = range[0];
8716 result->max_range = range[1];
8717 result->precision = precision;
8719 return error::kNoError;
8722 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8723 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8724 uint32 result_size = c.result_size;
8725 GLuint program_id = static_cast<GLuint>(c.program);
8726 Program* program = GetProgramInfoNotShader(
8727 program_id, "glGetAttachedShaders");
8729 return error::kNoError;
8731 typedef cmds::GetAttachedShaders::Result Result;
8732 uint32 max_count = Result::ComputeMaxResults(result_size);
8733 Result* result = GetSharedMemoryAs<Result*>(
8734 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8736 return error::kOutOfBounds;
8738 // Check that the client initialized the result.
8739 if (result->size != 0) {
8740 return error::kInvalidArguments;
8743 glGetAttachedShaders(
8744 program->service_id(), max_count, &count, result->GetData());
8745 for (GLsizei ii = 0; ii < count; ++ii) {
8746 if (!shader_manager()->GetClientId(result->GetData()[ii],
8747 &result->GetData()[ii])) {
8749 return error::kGenericError;
8752 result->SetNumResults(count);
8753 return error::kNoError;
8756 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8757 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8758 GLuint program_id = c.program;
8759 GLuint index = c.index;
8760 uint32 name_bucket_id = c.name_bucket_id;
8761 typedef cmds::GetActiveUniform::Result Result;
8762 Result* result = GetSharedMemoryAs<Result*>(
8763 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8765 return error::kOutOfBounds;
8767 // Check that the client initialized the result.
8768 if (result->success != 0) {
8769 return error::kInvalidArguments;
8771 Program* program = GetProgramInfoNotShader(
8772 program_id, "glGetActiveUniform");
8774 return error::kNoError;
8776 const Program::UniformInfo* uniform_info =
8777 program->GetUniformInfo(index);
8778 if (!uniform_info) {
8780 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8781 return error::kNoError;
8783 result->success = 1; // true.
8784 result->size = uniform_info->size;
8785 result->type = uniform_info->type;
8786 Bucket* bucket = CreateBucket(name_bucket_id);
8787 bucket->SetFromString(uniform_info->name.c_str());
8788 return error::kNoError;
8791 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
8792 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8793 GLuint program_id = c.program;
8794 GLuint index = c.index;
8795 uint32 name_bucket_id = c.name_bucket_id;
8796 typedef cmds::GetActiveAttrib::Result Result;
8797 Result* result = GetSharedMemoryAs<Result*>(
8798 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8800 return error::kOutOfBounds;
8802 // Check that the client initialized the result.
8803 if (result->success != 0) {
8804 return error::kInvalidArguments;
8806 Program* program = GetProgramInfoNotShader(
8807 program_id, "glGetActiveAttrib");
8809 return error::kNoError;
8811 const Program::VertexAttrib* attrib_info =
8812 program->GetAttribInfo(index);
8815 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
8816 return error::kNoError;
8818 result->success = 1; // true.
8819 result->size = attrib_info->size;
8820 result->type = attrib_info->type;
8821 Bucket* bucket = CreateBucket(name_bucket_id);
8822 bucket->SetFromString(attrib_info->name.c_str());
8823 return error::kNoError;
8826 error::Error GLES2DecoderImpl::HandleShaderBinary(
8827 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
8828 #if 1 // No binary shader support.
8829 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
8830 return error::kNoError;
8832 GLsizei n = static_cast<GLsizei>(c.n);
8834 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
8835 return error::kNoError;
8837 GLsizei length = static_cast<GLsizei>(c.length);
8839 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
8840 return error::kNoError;
8843 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8844 return error::kOutOfBounds;
8846 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8847 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8848 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8849 const void* binary = GetSharedMemoryAs<const void*>(
8850 c.binary_shm_id, c.binary_shm_offset, length);
8851 if (shaders == NULL || binary == NULL) {
8852 return error::kOutOfBounds;
8854 scoped_array<GLuint> service_ids(new GLuint[n]);
8855 for (GLsizei ii = 0; ii < n; ++ii) {
8856 Shader* shader = GetShader(shaders[ii]);
8858 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
8859 return error::kNoError;
8861 service_ids[ii] = shader->service_id();
8863 // TODO(gman): call glShaderBinary
8864 return error::kNoError;
8868 void GLES2DecoderImpl::DoSwapBuffers() {
8869 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8871 int this_frame_number = frame_number_++;
8872 // TRACE_EVENT for gpu tests:
8873 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
8874 TRACE_EVENT_SCOPE_THREAD,
8875 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8876 "width", (is_offscreen ? offscreen_size_.width() :
8877 surface_->GetSize().width()));
8878 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
8879 "offscreen", is_offscreen,
8880 "frame", this_frame_number);
8882 TRACE_EVENT_SYNTHETIC_DELAY("gpu.SwapBuffers");
8886 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8889 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8890 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8891 is_offscreen ? offscreen_size_ : surface_->GetSize());
8894 // If offscreen then don't actually SwapBuffers to the display. Just copy
8895 // the rendered frame to another frame buffer.
8897 TRACE_EVENT2("gpu", "Offscreen",
8898 "width", offscreen_size_.width(), "height", offscreen_size_.height());
8899 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8900 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8901 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8903 if (workarounds().needs_offscreen_buffer_workaround) {
8904 offscreen_saved_frame_buffer_->Create();
8908 // Allocate the offscreen saved color texture.
8909 DCHECK(offscreen_saved_color_format_);
8910 offscreen_saved_color_texture_->AllocateStorage(
8911 offscreen_size_, offscreen_saved_color_format_, false);
8913 offscreen_saved_frame_buffer_->AttachRenderTexture(
8914 offscreen_saved_color_texture_.get());
8915 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8916 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8917 GL_FRAMEBUFFER_COMPLETE) {
8918 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8919 << "because offscreen saved FBO was incomplete.";
8920 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8924 // Clear the offscreen color texture.
8925 // TODO(piman): Is this still necessary?
8927 ScopedFrameBufferBinder binder(this,
8928 offscreen_saved_frame_buffer_->id());
8929 glClearColor(0, 0, 0, 0);
8930 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8931 glDisable(GL_SCISSOR_TEST);
8932 glClear(GL_COLOR_BUFFER_BIT);
8933 RestoreClearState();
8937 UpdateParentTextureInfo();
8940 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
8942 ScopedGLErrorSuppressor suppressor(
8943 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
8945 if (IsOffscreenBufferMultisampled()) {
8946 // For multisampled buffers, resolve the frame buffer.
8947 ScopedResolvedFrameBufferBinder binder(this, true, false);
8949 ScopedFrameBufferBinder binder(this,
8950 offscreen_target_frame_buffer_->id());
8952 if (offscreen_target_buffer_preserved_) {
8953 // Copy the target frame buffer to the saved offscreen texture.
8954 offscreen_saved_color_texture_->Copy(
8955 offscreen_saved_color_texture_->size(),
8956 offscreen_saved_color_format_);
8958 // Flip the textures in the parent context via the texture manager.
8959 if (!!offscreen_saved_color_texture_info_.get())
8960 offscreen_saved_color_texture_info_->texture()->
8961 SetServiceId(offscreen_target_color_texture_->id());
8963 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8964 offscreen_target_frame_buffer_->AttachRenderTexture(
8965 offscreen_target_color_texture_.get());
8968 // Ensure the side effects of the copy are visible to the parent
8969 // context. There is no need to do this for ANGLE because it uses a
8970 // single D3D device for all contexts.
8971 if (!feature_info_->feature_flags().is_angle)
8975 if (!surface_->SwapBuffers()) {
8976 LOG(ERROR) << "Context lost because SwapBuffers failed.";
8977 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8982 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
8983 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
8984 Bucket* bucket = GetBucket(c.bucket_id);
8985 if (!bucket || bucket->size() == 0) {
8986 return error::kInvalidArguments;
8988 typedef cmds::EnableFeatureCHROMIUM::Result Result;
8989 Result* result = GetSharedMemoryAs<Result*>(
8990 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8992 return error::kOutOfBounds;
8994 // Check that the client initialized the result.
8996 return error::kInvalidArguments;
8998 std::string feature_str;
8999 if (!bucket->GetAsString(&feature_str)) {
9000 return error::kInvalidArguments;
9003 // TODO(gman): make this some kind of table to function pointer thingy.
9004 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9005 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9006 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9007 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9008 // TODO(gman): decide how to remove the need for this const_cast.
9009 // I could make validators_ non const but that seems bad as this is the only
9010 // place it is needed. I could make some special friend class of validators
9011 // just to allow this to set them. That seems silly. I could refactor this
9012 // code to use the extension mechanism or the initialization attributes to
9013 // turn this feature on. Given that the only real point of this is to make
9014 // the conformance tests pass and given that there is lots of real work that
9015 // needs to be done it seems like refactoring for one to one of those
9016 // methods is a very low priority.
9017 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9018 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9019 force_webgl_glsl_validation_ = true;
9020 InitializeShaderTranslator();
9022 return error::kNoError;
9025 *result = 1; // true.
9026 return error::kNoError;
9029 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9030 uint32 immediate_data_size,
9031 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9032 Bucket* bucket = CreateBucket(c.bucket_id);
9033 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9034 info->Initialize(disallowed_features_);
9035 bucket->SetFromString(info->extensions().c_str());
9036 return error::kNoError;
9039 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9040 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9041 Bucket* bucket = GetBucket(c.bucket_id);
9042 if (!bucket || bucket->size() == 0) {
9043 return error::kInvalidArguments;
9045 std::string feature_str;
9046 if (!bucket->GetAsString(&feature_str)) {
9047 return error::kInvalidArguments;
9050 bool desire_webgl_glsl_validation =
9051 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9052 bool desire_standard_derivatives = false;
9053 bool desire_frag_depth = false;
9054 bool desire_draw_buffers = false;
9055 if (force_webgl_glsl_validation_) {
9056 desire_standard_derivatives =
9057 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9059 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9060 desire_draw_buffers =
9061 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9064 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9065 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9066 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9067 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9068 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9069 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9070 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9071 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9072 InitializeShaderTranslator();
9075 UpdateCapabilities();
9077 return error::kNoError;
9080 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9081 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9082 GLuint count = c.count;
9084 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9085 return error::kOutOfBounds;
9087 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9088 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9089 if (pnames == NULL) {
9090 return error::kOutOfBounds;
9093 // We have to copy them since we use them twice so the client
9094 // can't change them between the time we validate them and the time we use
9096 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9097 memcpy(enums.get(), pnames, pnames_size);
9099 // Count up the space needed for the result.
9100 uint32 num_results = 0;
9101 for (GLuint ii = 0; ii < count; ++ii) {
9102 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9104 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9105 "glGetMulitpleCHROMIUM", enums[ii], "pname");
9106 return error::kNoError;
9108 // Num will never be more than 4.
9110 if (!SafeAddUint32(num_results, num, &num_results)) {
9111 return error::kOutOfBounds;
9115 uint32 result_size = 0;
9116 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9117 return error::kOutOfBounds;
9120 if (result_size != static_cast<uint32>(c.size)) {
9123 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
9124 return error::kNoError;
9127 GLint* results = GetSharedMemoryAs<GLint*>(
9128 c.results_shm_id, c.results_shm_offset, result_size);
9129 if (results == NULL) {
9130 return error::kOutOfBounds;
9133 // Check the results have been cleared in case the context was lost.
9134 for (uint32 ii = 0; ii < num_results; ++ii) {
9136 return error::kInvalidArguments;
9141 GLint* start = results;
9142 for (GLuint ii = 0; ii < count; ++ii) {
9143 GLsizei num_written = 0;
9144 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9145 !GetHelper(enums[ii], results, &num_written)) {
9146 DoGetIntegerv(enums[ii], results);
9148 results += num_written;
9151 // Just to verify. Should this be a DCHECK?
9152 if (static_cast<uint32>(results - start) != num_results) {
9153 return error::kOutOfBounds;
9156 return error::kNoError;
9159 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9160 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9161 GLuint program_id = static_cast<GLuint>(c.program);
9162 uint32 bucket_id = c.bucket_id;
9163 Bucket* bucket = CreateBucket(bucket_id);
9164 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9165 Program* program = NULL;
9166 program = GetProgram(program_id);
9167 if (!program || !program->IsValid()) {
9168 return error::kNoError;
9170 program->GetProgramInfo(program_manager(), bucket);
9171 return error::kNoError;
9174 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9175 switch (reset_status_) {
9177 // TODO(kbr): improve the precision of the error code in this case.
9178 // Consider delegating to context for error code if MakeCurrent fails.
9179 return error::kUnknown;
9180 case GL_GUILTY_CONTEXT_RESET_ARB:
9181 return error::kGuilty;
9182 case GL_INNOCENT_CONTEXT_RESET_ARB:
9183 return error::kInnocent;
9184 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9185 return error::kUnknown;
9189 return error::kUnknown;
9192 bool GLES2DecoderImpl::WasContextLost() {
9193 if (reset_status_ != GL_NO_ERROR) {
9196 if (context_->WasAllocatedUsingRobustnessExtension()) {
9197 GLenum status = GL_NO_ERROR;
9198 if (has_robustness_extension_)
9199 status = glGetGraphicsResetStatusARB();
9200 if (status != GL_NO_ERROR) {
9201 // The graphics card was reset. Signal a lost context to the application.
9202 reset_status_ = status;
9203 reset_by_robustness_extension_ = true;
9204 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9205 << " context lost via ARB/EXT_robustness. Reset status = "
9206 << GLES2Util::GetStringEnum(status);
9213 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9214 return WasContextLost() && reset_by_robustness_extension_;
9217 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9218 // Only loses the context once.
9219 if (reset_status_ != GL_NO_ERROR) {
9223 // Marks this context as lost.
9224 reset_status_ = reset_status;
9225 current_decoder_error_ = error::kLostContext;
9228 error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9229 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
9230 GLenum current = static_cast<GLenum>(c.current);
9231 GLenum other = static_cast<GLenum>(c.other);
9232 if (!validators_->reset_status.IsValid(current)) {
9233 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9234 "glLoseContextCHROMIUM", current, "current");
9236 if (!validators_->reset_status.IsValid(other)) {
9237 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
9239 group_->LoseContexts(other);
9240 reset_status_ = current;
9241 current_decoder_error_ = error::kLostContext;
9242 return error::kLostContext;
9245 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9246 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9247 return error::kUnknownCommand;
9250 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9251 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9252 if (wait_sync_point_callback_.is_null())
9253 return error::kNoError;
9255 return wait_sync_point_callback_.Run(c.sync_point) ?
9256 error::kNoError : error::kDeferCommandUntilLater;
9259 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9260 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9261 if (surface_->DeferDraws())
9262 return error::kDeferCommandUntilLater;
9263 if (!surface_->SetBackbufferAllocation(false))
9264 return error::kLostContext;
9265 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9266 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9267 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9268 return error::kNoError;
9271 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9272 GLsizei n, const GLuint* client_ids) {
9273 for (GLsizei ii = 0; ii < n; ++ii) {
9274 if (query_manager_->GetQuery(client_ids[ii])) {
9278 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
9282 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9283 GLsizei n, const GLuint* client_ids) {
9284 for (GLsizei ii = 0; ii < n; ++ii) {
9285 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9286 if (query && !query->IsDeleted()) {
9287 ContextState::QueryMap::iterator it =
9288 state_.current_queries.find(query->target());
9289 if (it != state_.current_queries.end())
9290 state_.current_queries.erase(it);
9292 query->Destroy(true);
9293 query_manager_->RemoveQuery(client_ids[ii]);
9298 bool GLES2DecoderImpl::ProcessPendingQueries() {
9299 if (query_manager_.get() == NULL) {
9302 if (!query_manager_->ProcessPendingQueries()) {
9303 current_decoder_error_ = error::kOutOfBounds;
9305 return query_manager_->HavePendingQueries();
9308 // Note that if there are no pending readpixels right now,
9309 // this function will call the callback immediately.
9310 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9311 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9312 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9318 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9319 while (!pending_readpixel_fences_.empty() &&
9320 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9321 std::vector<base::Closure> callbacks =
9322 pending_readpixel_fences_.front()->callbacks;
9323 pending_readpixel_fences_.pop();
9324 for (size_t i = 0; i < callbacks.size(); i++) {
9330 bool GLES2DecoderImpl::HasMoreIdleWork() {
9331 return !pending_readpixel_fences_.empty() ||
9332 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9335 void GLES2DecoderImpl::PerformIdleWork() {
9336 ProcessPendingReadPixels();
9337 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9339 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9340 ProcessFinishedAsyncTransfers();
9343 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9344 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9345 GLenum target = static_cast<GLenum>(c.target);
9346 GLuint client_id = static_cast<GLuint>(c.id);
9347 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9348 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9351 case GL_COMMANDS_ISSUED_CHROMIUM:
9352 case GL_LATENCY_QUERY_CHROMIUM:
9353 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9354 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9355 case GL_GET_ERROR_QUERY_CHROMIUM:
9358 if (!features().occlusion_query_boolean) {
9360 GL_INVALID_OPERATION, "glBeginQueryEXT",
9361 "not enabled for occlusion queries");
9362 return error::kNoError;
9367 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9369 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9370 return error::kNoError;
9373 if (client_id == 0) {
9374 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9375 return error::kNoError;
9378 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9380 // TODO(gman): Decide if we need this check.
9382 // Checks id was made by glGenQueries
9384 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9385 // for all Query ids but from the POV of the command buffer service maybe
9388 // The client can enforce this. I don't think the service cares.
9390 // IdAllocatorInterface* id_allocator =
9391 // group_->GetIdAllocator(id_namespaces::kQueries);
9392 // if (!id_allocator->InUse(client_id)) {
9393 // LOCAL_SET_GL_ERROR(
9394 // GL_INVALID_OPERATION,
9395 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
9396 // return error::kNoError;
9398 query = query_manager_->CreateQuery(
9399 target, client_id, sync_shm_id, sync_shm_offset);
9402 if (query->target() != target) {
9404 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9405 return error::kNoError;
9406 } else if (query->shm_id() != sync_shm_id ||
9407 query->shm_offset() != sync_shm_offset) {
9408 DLOG(ERROR) << "Shared memory used by query not the same as before";
9409 return error::kInvalidArguments;
9412 if (!query_manager_->BeginQuery(query)) {
9413 return error::kOutOfBounds;
9416 state_.current_queries[target] = query;
9417 return error::kNoError;
9420 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9421 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9422 GLenum target = static_cast<GLenum>(c.target);
9423 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9424 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9426 if (it == state_.current_queries.end()) {
9428 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9429 return error::kNoError;
9432 QueryManager::Query* query = it->second.get();
9433 if (!query_manager_->EndQuery(query, submit_count)) {
9434 return error::kOutOfBounds;
9437 query_manager_->ProcessPendingTransferQueries();
9439 state_.current_queries.erase(it);
9440 return error::kNoError;
9443 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9444 GLsizei n, const GLuint* client_ids) {
9445 for (GLsizei ii = 0; ii < n; ++ii) {
9446 if (GetVertexAttribManager(client_ids[ii])) {
9451 if (!features().native_vertex_array_object) {
9453 for (GLsizei ii = 0; ii < n; ++ii) {
9454 CreateVertexAttribManager(client_ids[ii], 0);
9457 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9459 glGenVertexArraysOES(n, service_ids.get());
9460 for (GLsizei ii = 0; ii < n; ++ii) {
9461 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9468 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9469 GLsizei n, const GLuint* client_ids) {
9470 for (GLsizei ii = 0; ii < n; ++ii) {
9471 VertexAttribManager* vao =
9472 GetVertexAttribManager(client_ids[ii]);
9473 if (vao && !vao->IsDeleted()) {
9474 if (state_.vertex_attrib_manager.get() == vao) {
9475 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
9477 RemoveVertexAttribManager(client_ids[ii]);
9482 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9483 VertexAttribManager* vao = NULL;
9484 GLuint service_id = 0;
9485 if (client_id != 0) {
9486 vao = GetVertexAttribManager(client_id);
9488 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9489 // only allows names that have been previously generated. As such, we do
9490 // not generate new names here.
9492 GL_INVALID_OPERATION,
9493 "glBindVertexArrayOES", "bad vertex array id.");
9494 current_decoder_error_ = error::kNoError;
9497 service_id = vao->service_id();
9500 vao = default_vertex_attrib_manager_.get();
9503 // Only set the VAO state if it's changed
9504 if (state_.vertex_attrib_manager.get() != vao) {
9505 state_.vertex_attrib_manager = vao;
9506 if (!features().native_vertex_array_object) {
9507 EmulateVertexArrayState();
9509 glBindVertexArrayOES(service_id);
9514 // Used when OES_vertex_array_object isn't natively supported
9515 void GLES2DecoderImpl::EmulateVertexArrayState() {
9516 // Setup the Vertex attribute state
9517 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9518 RestoreStateForAttrib(vv);
9521 // Setup the element buffer
9522 Buffer* element_array_buffer =
9523 state_.vertex_attrib_manager->element_array_buffer();
9524 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9525 element_array_buffer ? element_array_buffer->service_id() : 0);
9528 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9529 const VertexAttribManager* vao =
9530 GetVertexAttribManager(client_id);
9531 return vao && vao->IsValid() && !vao->IsDeleted();
9534 #if defined(OS_MACOSX)
9535 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9536 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9538 if (it != texture_to_io_surface_map_.end()) {
9539 // Found a previous IOSurface bound to this texture; release it.
9540 CFTypeRef surface = it->second;
9542 texture_to_io_surface_map_.erase(it);
9547 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9548 GLenum target, GLsizei width, GLsizei height,
9549 GLuint io_surface_id, GLuint plane) {
9550 #if defined(OS_MACOSX)
9551 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9553 GL_INVALID_OPERATION,
9554 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9558 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9559 if (!surface_support) {
9561 GL_INVALID_OPERATION,
9562 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
9566 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9567 // This might be supported in the future, and if we could require
9568 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9569 // could delete a lot of code. For now, perform strict validation so we
9570 // know what's going on.
9572 GL_INVALID_OPERATION,
9573 "glTexImageIOSurface2DCHROMIUM",
9574 "requires TEXTURE_RECTANGLE_ARB target");
9578 // Default target might be conceptually valid, but disallow it to avoid
9580 TextureRef* texture_ref =
9581 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9584 GL_INVALID_OPERATION,
9585 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9589 // Look up the new IOSurface. Note that because of asynchrony
9590 // between processes this might fail; during live resizing the
9591 // plugin process might allocate and release an IOSurface before
9592 // this process gets a chance to look it up. Hold on to any old
9593 // IOSurface in this case.
9594 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9597 GL_INVALID_OPERATION,
9598 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9602 // Release any IOSurface previously bound to this texture.
9603 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9605 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9606 texture_to_io_surface_map_.insert(
9607 std::make_pair(texture_ref->service_id(), surface));
9609 CGLContextObj context =
9610 static_cast<CGLContextObj>(context_->GetHandle());
9612 CGLError err = surface_support->CGLTexImageIOSurface2D(
9619 GL_UNSIGNED_INT_8_8_8_8_REV,
9623 if (err != kCGLNoError) {
9625 GL_INVALID_OPERATION,
9626 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9630 texture_manager()->SetLevelInfo(
9631 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9632 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9635 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9636 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9640 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9641 switch (internalformat) {
9652 case GL_LUMINANCE8_ALPHA8_EXT:
9653 return GL_LUMINANCE_ALPHA;
9654 case GL_LUMINANCE8_EXT:
9655 return GL_LUMINANCE;
9658 case GL_RGBA32F_EXT:
9662 case GL_ALPHA32F_EXT:
9664 case GL_LUMINANCE32F_EXT:
9665 return GL_LUMINANCE;
9666 case GL_LUMINANCE_ALPHA32F_EXT:
9667 return GL_LUMINANCE_ALPHA;
9668 case GL_RGBA16F_EXT:
9672 case GL_ALPHA16F_EXT:
9674 case GL_LUMINANCE16F_EXT:
9675 return GL_LUMINANCE;
9676 case GL_LUMINANCE_ALPHA16F_EXT:
9677 return GL_LUMINANCE_ALPHA;
9685 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9686 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9687 GLenum internal_format, GLenum dest_type) {
9688 TextureRef* dest_texture_ref = GetTexture(dest_id);
9689 TextureRef* source_texture_ref = GetTexture(source_id);
9691 if (!source_texture_ref || !dest_texture_ref) {
9693 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9697 if (GL_TEXTURE_2D != target) {
9699 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9703 Texture* source_texture = source_texture_ref->texture();
9704 Texture* dest_texture = dest_texture_ref->texture();
9705 if (dest_texture->target() != GL_TEXTURE_2D ||
9706 (source_texture->target() != GL_TEXTURE_2D &&
9707 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9708 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9709 "glCopyTextureCHROMIUM",
9710 "invalid texture target binding");
9714 int source_width, source_height, dest_width, dest_height;
9716 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9717 gfx::GLImage* image =
9718 source_texture->GetLevelImage(source_texture->target(), 0);
9721 GL_INVALID_OPERATION,
9722 "glCopyTextureChromium", "No external image");
9725 gfx::Size size = image->GetSize();
9726 source_width = size.width();
9727 source_height = size.height();
9728 if (source_width <= 0 || source_height <= 0) {
9731 "glCopyTextureChromium", "invalid image size");
9735 if (!source_texture->GetLevelSize(
9736 source_texture->target(), 0, &source_width, &source_height)) {
9737 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9738 "glCopyTextureChromium",
9739 "source texture has no level 0");
9743 // Check that this type of texture is allowed.
9744 if (!texture_manager()->ValidForTarget(
9745 source_texture->target(), level, source_width, source_height, 1)) {
9747 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9752 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9753 // needed because it takes 10s of milliseconds to initialize.
9754 if (!copy_texture_CHROMIUM_.get()) {
9755 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9756 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9757 copy_texture_CHROMIUM_->Initialize(this);
9758 RestoreCurrentFramebufferBindings();
9759 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9763 GLenum dest_type_previous;
9764 GLenum dest_internal_format;
9765 bool dest_level_defined = dest_texture->GetLevelSize(
9766 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9768 if (dest_level_defined) {
9769 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9770 &dest_internal_format);
9773 // Resize the destination texture to the dimensions of the source texture.
9774 if (!dest_level_defined || dest_width != source_width ||
9775 dest_height != source_height ||
9776 dest_internal_format != internal_format ||
9777 dest_type_previous != dest_type) {
9778 // Ensure that the glTexImage2D succeeds.
9779 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9780 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9782 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9783 0, internal_format, dest_type, NULL);
9784 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9785 if (error != GL_NO_ERROR) {
9786 RestoreCurrentTexture2DBindings(&state_);
9790 texture_manager()->SetLevelInfo(
9791 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9792 source_height, 1, 0, internal_format, dest_type, true);
9794 texture_manager()->SetLevelCleared(
9795 dest_texture_ref, GL_TEXTURE_2D, level, true);
9798 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9800 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9801 // before presenting.
9802 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9803 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9804 // instead of using default matrix crbug.com/226218.
9805 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9806 0.0f, 1.0f, 0.0f, 0.0f,
9807 0.0f, 0.0f, 1.0f, 0.0f,
9808 0.0f, 0.0f, 0.0f, 1.0f};
9809 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9811 source_texture->target(),
9812 dest_texture->target(),
9813 source_texture->service_id(),
9814 dest_texture->service_id(), level,
9815 source_width, source_height,
9817 unpack_premultiply_alpha_,
9818 unpack_unpremultiply_alpha_,
9821 copy_texture_CHROMIUM_->DoCopyTexture(
9823 source_texture->target(),
9824 dest_texture->target(),
9825 source_texture->service_id(),
9826 dest_texture->service_id(), level,
9827 source_width, source_height,
9829 unpack_premultiply_alpha_,
9830 unpack_unpremultiply_alpha_);
9833 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
9836 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9837 switch (internalformat) {
9839 return GL_UNSIGNED_SHORT_5_6_5;
9841 return GL_UNSIGNED_SHORT_4_4_4_4;
9843 return GL_UNSIGNED_SHORT_5_5_5_1;
9845 return GL_UNSIGNED_BYTE;
9847 return GL_UNSIGNED_BYTE;
9848 case GL_LUMINANCE8_ALPHA8_EXT:
9849 return GL_UNSIGNED_BYTE;
9850 case GL_LUMINANCE8_EXT:
9851 return GL_UNSIGNED_BYTE;
9853 return GL_UNSIGNED_BYTE;
9854 case GL_RGBA32F_EXT:
9858 case GL_ALPHA32F_EXT:
9860 case GL_LUMINANCE32F_EXT:
9862 case GL_LUMINANCE_ALPHA32F_EXT:
9864 case GL_RGBA16F_EXT:
9865 return GL_HALF_FLOAT_OES;
9867 return GL_HALF_FLOAT_OES;
9868 case GL_ALPHA16F_EXT:
9869 return GL_HALF_FLOAT_OES;
9870 case GL_LUMINANCE16F_EXT:
9871 return GL_HALF_FLOAT_OES;
9872 case GL_LUMINANCE_ALPHA16F_EXT:
9873 return GL_HALF_FLOAT_OES;
9875 return GL_UNSIGNED_BYTE;
9881 void GLES2DecoderImpl::DoTexStorage2DEXT(
9884 GLenum internal_format,
9887 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
9888 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
9889 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
9891 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
9894 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9898 GL_INVALID_OPERATION,
9899 "glTexStorage2DEXT", "unknown texture for target");
9902 Texture* texture = texture_ref->texture();
9903 if (texture->IsAttachedToFramebuffer()) {
9904 framebuffer_state_.clear_state_dirty = true;
9906 if (texture->IsImmutable()) {
9908 GL_INVALID_OPERATION,
9909 "glTexStorage2DEXT", "texture is immutable");
9913 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9914 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9917 GLsizei level_width = width;
9918 GLsizei level_height = height;
9919 uint32 estimated_size = 0;
9920 for (int ii = 0; ii < levels; ++ii) {
9921 uint32 level_size = 0;
9922 if (!GLES2Util::ComputeImageDataSizes(
9923 level_width, level_height, format, type, state_.unpack_alignment,
9924 &estimated_size, NULL, NULL) ||
9925 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
9927 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
9930 level_width = std::max(1, level_width >> 1);
9931 level_height = std::max(1, level_height >> 1);
9933 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9935 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
9940 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
9941 glTexStorage2DEXT(target, levels, internal_format, width, height);
9942 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
9943 if (error == GL_NO_ERROR) {
9944 GLsizei level_width = width;
9945 GLsizei level_height = height;
9946 for (int ii = 0; ii < levels; ++ii) {
9947 texture_manager()->SetLevelInfo(
9948 texture_ref, target, ii, format,
9949 level_width, level_height, 1, 0, format, type, false);
9950 level_width = std::max(1, level_width >> 1);
9951 level_height = std::max(1, level_height >> 1);
9953 texture->SetImmutable(true);
9957 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
9958 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
9959 return error::kUnknownCommand;
9962 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9963 const GLbyte* mailbox) {
9964 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
9965 "context", logger_.GetLogPrefix(),
9966 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9968 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9972 GL_INVALID_OPERATION,
9973 "glProduceTextureCHROMIUM", "unknown texture for target");
9977 Texture* produced = texture_manager()->Produce(texture_ref);
9980 GL_INVALID_OPERATION,
9981 "glProduceTextureCHROMIUM", "invalid texture");
9985 if (!group_->mailbox_manager()->ProduceTexture(
9987 *reinterpret_cast<const MailboxName*>(mailbox),
9990 GL_INVALID_OPERATION,
9991 "glProduceTextureCHROMIUM", "invalid mailbox name");
9996 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9997 const GLbyte* mailbox) {
9998 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
9999 "context", logger_.GetLogPrefix(),
10000 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
10002 scoped_refptr<TextureRef> texture_ref =
10003 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10004 if (!texture_ref.get()) {
10005 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10006 "glConsumeTextureCHROMIUM",
10007 "unknown texture for target");
10010 GLuint client_id = texture_ref->client_id();
10012 LOCAL_SET_GL_ERROR(
10013 GL_INVALID_OPERATION,
10014 "glConsumeTextureCHROMIUM", "unknown texture for target");
10018 group_->mailbox_manager()->ConsumeTexture(
10020 *reinterpret_cast<const MailboxName*>(mailbox));
10022 LOCAL_SET_GL_ERROR(
10023 GL_INVALID_OPERATION,
10024 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10027 if (texture->target() != target) {
10028 LOCAL_SET_GL_ERROR(
10029 GL_INVALID_OPERATION,
10030 "glConsumeTextureCHROMIUM", "invalid target");
10034 DeleteTexturesHelper(1, &client_id);
10035 texture_ref = texture_manager()->Consume(client_id, texture);
10036 glBindTexture(target, texture_ref->service_id());
10038 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10039 unit.bind_target = target;
10041 case GL_TEXTURE_2D:
10042 unit.bound_texture_2d = texture_ref;
10044 case GL_TEXTURE_CUBE_MAP:
10045 unit.bound_texture_cube_map = texture_ref;
10047 case GL_TEXTURE_EXTERNAL_OES:
10048 unit.bound_texture_external_oes = texture_ref;
10050 case GL_TEXTURE_RECTANGLE_ARB:
10051 unit.bound_texture_rectangle_arb = texture_ref;
10054 NOTREACHED(); // Validation should prevent us getting here.
10059 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10060 GLsizei length, const GLchar* marker) {
10064 debug_marker_manager_.SetMarker(
10065 length ? std::string(marker, length) : std::string(marker));
10068 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10069 GLsizei length, const GLchar* marker) {
10073 std::string name = length ? std::string(marker, length) : std::string(marker);
10074 debug_marker_manager_.PushGroup(name);
10075 gpu_tracer_->Begin(name, kTraceGroupMarker);
10078 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10079 debug_marker_manager_.PopGroup();
10080 gpu_tracer_->End(kTraceGroupMarker);
10083 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10084 GLenum target, GLint image_id) {
10085 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10087 // Default target might be conceptually valid, but disallow it to avoid
10089 TextureRef* texture_ref =
10090 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10091 if (!texture_ref) {
10092 LOCAL_SET_GL_ERROR(
10093 GL_INVALID_OPERATION,
10094 "glBindTexImage2DCHROMIUM", "no texture bound");
10098 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10100 LOCAL_SET_GL_ERROR(
10101 GL_INVALID_OPERATION,
10102 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10107 ScopedGLErrorSuppressor suppressor(
10108 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10109 if (!gl_image->BindTexImage(target)) {
10110 LOCAL_SET_GL_ERROR(
10111 GL_INVALID_OPERATION,
10112 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10117 gfx::Size size = gl_image->GetSize();
10118 texture_manager()->SetLevelInfo(
10119 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10120 GL_RGBA, GL_UNSIGNED_BYTE, true);
10121 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10124 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10125 GLenum target, GLint image_id) {
10126 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10128 // Default target might be conceptually valid, but disallow it to avoid
10130 TextureRef* texture_ref =
10131 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10132 if (!texture_ref) {
10133 LOCAL_SET_GL_ERROR(
10134 GL_INVALID_OPERATION,
10135 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10139 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10141 LOCAL_SET_GL_ERROR(
10142 GL_INVALID_OPERATION,
10143 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10147 // Do nothing when image is not currently bound.
10148 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10152 ScopedGLErrorSuppressor suppressor(
10153 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10154 gl_image->ReleaseTexImage(target);
10157 texture_manager()->SetLevelInfo(
10158 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10159 GL_RGBA, GL_UNSIGNED_BYTE, false);
10162 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10163 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10164 Bucket* bucket = GetBucket(c.bucket_id);
10165 if (!bucket || bucket->size() == 0) {
10166 return error::kInvalidArguments;
10168 std::string command_name;
10169 if (!bucket->GetAsString(&command_name)) {
10170 return error::kInvalidArguments;
10172 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10173 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10174 LOCAL_SET_GL_ERROR(
10175 GL_INVALID_OPERATION,
10176 "glTraceBeginCHROMIUM", "unable to create begin trace");
10177 return error::kNoError;
10179 return error::kNoError;
10182 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10183 if (gpu_tracer_->CurrentName().empty()) {
10184 LOCAL_SET_GL_ERROR(
10185 GL_INVALID_OPERATION,
10186 "glTraceEndCHROMIUM", "no trace begin found");
10189 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10190 gpu_tracer_->End(kTraceCHROMIUM);
10193 void GLES2DecoderImpl::DoDrawBuffersEXT(
10194 GLsizei count, const GLenum* bufs) {
10195 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10196 LOCAL_SET_GL_ERROR(
10198 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10202 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10204 for (GLsizei i = 0; i < count; ++i) {
10205 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10206 bufs[i] != GL_NONE) {
10207 LOCAL_SET_GL_ERROR(
10208 GL_INVALID_OPERATION,
10209 "glDrawBuffersEXT",
10210 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10214 glDrawBuffersARB(count, bufs);
10215 framebuffer->SetDrawBuffers(count, bufs);
10216 } else { // backbuffer
10218 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10219 LOCAL_SET_GL_ERROR(
10220 GL_INVALID_OPERATION,
10221 "glDrawBuffersEXT",
10222 "more than one buffer or bufs not GL_NONE or GL_BACK");
10225 GLenum mapped_buf = bufs[0];
10226 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10227 bufs[0] == GL_BACK) {
10228 mapped_buf = GL_COLOR_ATTACHMENT0;
10230 glDrawBuffersARB(count, &mapped_buf);
10231 group_->set_draw_buffer(bufs[0]);
10235 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10236 const char* function_name,
10237 TextureRef* texture_ref,
10240 const void * data) {
10241 // We only support async uploads to 2D textures for now.
10242 if (GL_TEXTURE_2D != target) {
10243 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10246 // We only support uploads to level zero for now.
10248 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10251 // A transfer buffer must be bound, even for asyncTexImage2D.
10252 if (data == NULL) {
10253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10256 // We only support one async transfer in progress.
10257 if (!texture_ref ||
10258 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10259 LOCAL_SET_GL_ERROR(
10260 GL_INVALID_OPERATION,
10261 function_name, "transfer already in progress");
10267 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10268 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10269 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10270 GLenum target = static_cast<GLenum>(c.target);
10271 GLint level = static_cast<GLint>(c.level);
10272 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10273 // unsigned integer for internalformat.
10274 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10275 GLsizei width = static_cast<GLsizei>(c.width);
10276 GLsizei height = static_cast<GLsizei>(c.height);
10277 GLint border = static_cast<GLint>(c.border);
10278 GLenum format = static_cast<GLenum>(c.format);
10279 GLenum type = static_cast<GLenum>(c.type);
10280 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10281 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10282 uint32 pixels_size;
10284 // TODO(epenner): Move this and copies of this memory validation
10285 // into ValidateTexImage2D step.
10286 if (!GLES2Util::ComputeImageDataSizes(
10287 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10289 return error::kOutOfBounds;
10291 const void* pixels = NULL;
10292 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10293 pixels = GetSharedMemoryAs<const void*>(
10294 pixels_shm_id, pixels_shm_offset, pixels_size);
10296 return error::kOutOfBounds;
10300 TextureManager::DoTextImage2DArguments args = {
10301 target, level, internal_format, width, height, border, format, type,
10302 pixels, pixels_size};
10303 TextureRef* texture_ref;
10304 // All the normal glTexSubImage2D validation.
10305 if (!texture_manager()->ValidateTexImage2D(
10306 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10307 return error::kNoError;
10310 // Extra async validation.
10311 Texture* texture = texture_ref->texture();
10312 if (!ValidateAsyncTransfer(
10313 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10314 return error::kNoError;
10316 // Don't allow async redefinition of a textures.
10317 if (texture->IsDefined()) {
10318 LOCAL_SET_GL_ERROR(
10319 GL_INVALID_OPERATION,
10320 "glAsyncTexImage2DCHROMIUM", "already defined");
10321 return error::kNoError;
10324 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10325 LOCAL_SET_GL_ERROR(
10326 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10327 return error::kNoError;
10330 // We know the memory/size is safe, so get the real shared memory since
10331 // it might need to be duped to prevent use-after-free of the memory.
10332 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
10333 base::SharedMemory* shared_memory = buffer.shared_memory;
10334 uint32 shm_size = buffer.size;
10335 uint32 shm_data_offset = c.pixels_shm_offset;
10336 uint32 shm_data_size = pixels_size;
10338 // Setup the parameters.
10339 AsyncTexImage2DParams tex_params = {
10340 target, level, static_cast<GLenum>(internal_format),
10341 width, height, border, format, type};
10342 AsyncMemoryParams mem_params = {
10343 shared_memory, shm_size, shm_data_offset, shm_data_size};
10345 // Set up the async state if needed, and make the texture
10346 // immutable so the async state stays valid. The level info
10347 // is set up lazily when the transfer completes.
10348 AsyncPixelTransferDelegate* delegate =
10349 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10351 texture->SetImmutable(true);
10353 delegate->AsyncTexImage2D(
10356 base::Bind(&TextureManager::SetLevelInfoFromParams,
10357 // The callback is only invoked if the transfer delegate still
10358 // exists, which implies through manager->texture_ref->state
10359 // ownership that both of these pointers are valid.
10360 base::Unretained(texture_manager()),
10361 base::Unretained(texture_ref),
10363 return error::kNoError;
10366 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10367 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10368 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10369 GLenum target = static_cast<GLenum>(c.target);
10370 GLint level = static_cast<GLint>(c.level);
10371 GLint xoffset = static_cast<GLint>(c.xoffset);
10372 GLint yoffset = static_cast<GLint>(c.yoffset);
10373 GLsizei width = static_cast<GLsizei>(c.width);
10374 GLsizei height = static_cast<GLsizei>(c.height);
10375 GLenum format = static_cast<GLenum>(c.format);
10376 GLenum type = static_cast<GLenum>(c.type);
10378 // TODO(epenner): Move this and copies of this memory validation
10379 // into ValidateTexSubImage2D step.
10381 if (!GLES2Util::ComputeImageDataSizes(
10382 width, height, format, type, state_.unpack_alignment, &data_size,
10384 return error::kOutOfBounds;
10386 const void* pixels = GetSharedMemoryAs<const void*>(
10387 c.data_shm_id, c.data_shm_offset, data_size);
10389 // All the normal glTexSubImage2D validation.
10390 error::Error error = error::kNoError;
10391 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10392 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10396 // Extra async validation.
10397 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10399 Texture* texture = texture_ref->texture();
10400 if (!ValidateAsyncTransfer(
10401 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10402 return error::kNoError;
10404 // Guarantee async textures are always 'cleared' as follows:
10405 // - AsyncTexImage2D can not redefine an existing texture
10406 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10407 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10408 // - Textures become immutable after an async call.
10409 // This way we know in all cases that an async texture is always clear.
10410 if (!texture->SafeToRenderFrom()) {
10411 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10413 LOCAL_SET_GL_ERROR(
10415 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10416 return error::kNoError;
10420 // We know the memory/size is safe, so get the real shared memory since
10421 // it might need to be duped to prevent use-after-free of the memory.
10422 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
10423 base::SharedMemory* shared_memory = buffer.shared_memory;
10424 uint32 shm_size = buffer.size;
10425 uint32 shm_data_offset = c.data_shm_offset;
10426 uint32 shm_data_size = data_size;
10428 // Setup the parameters.
10429 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10430 width, height, format, type};
10431 AsyncMemoryParams mem_params = {shared_memory, shm_size,
10432 shm_data_offset, shm_data_size};
10433 AsyncPixelTransferDelegate* delegate =
10434 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10436 // TODO(epenner): We may want to enforce exclusive use
10437 // of async APIs in which case this should become an error,
10438 // (the texture should have been async defined).
10439 AsyncTexImage2DParams define_params = {target, level,
10441 texture->GetLevelSize(target, level, &define_params.width,
10442 &define_params.height);
10443 texture->GetLevelType(target, level, &define_params.type,
10444 &define_params.internal_format);
10445 // Set up the async state if needed, and make the texture
10446 // immutable so the async state stays valid.
10447 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10448 texture_ref, define_params);
10449 texture->SetImmutable(true);
10452 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10453 return error::kNoError;
10456 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10457 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10458 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10459 GLenum target = static_cast<GLenum>(c.target);
10461 if (GL_TEXTURE_2D != target) {
10462 LOCAL_SET_GL_ERROR(
10463 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10464 return error::kNoError;
10466 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10468 if (!texture_ref) {
10469 LOCAL_SET_GL_ERROR(
10470 GL_INVALID_OPERATION,
10471 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10472 return error::kNoError;
10474 AsyncPixelTransferDelegate* delegate =
10475 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10477 LOCAL_SET_GL_ERROR(
10478 GL_INVALID_OPERATION,
10479 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10480 return error::kNoError;
10482 delegate->WaitForTransferCompletion();
10483 ProcessFinishedAsyncTransfers();
10484 return error::kNoError;
10487 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10488 TextureRef* texture_ref) {
10489 Texture* texture = texture_ref->texture();
10490 DoDidUseTexImageIfNeeded(texture, texture->target());
10493 // Include the auto-generated part of this file. We split this because it means
10494 // we can easily edit the non-auto generated parts right here in this file
10495 // instead of having to edit some template or the code generator.
10496 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10498 } // namespace gles2