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/atomicops.h"
18 #include "base/bind.h"
19 #include "base/command_line.h"
20 #include "base/debug/trace_event.h"
21 #if defined(OS_MACOSX)
22 #include "base/mac/scoped_cftyperef.h"
24 #include "base/memory/scoped_ptr.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/id_allocator.h"
32 #include "gpu/command_buffer/common/mailbox.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
35 #include "gpu/command_buffer/service/buffer_manager.h"
36 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
37 #include "gpu/command_buffer/service/context_group.h"
38 #include "gpu/command_buffer/service/context_state.h"
39 #include "gpu/command_buffer/service/error_state.h"
40 #include "gpu/command_buffer/service/feature_info.h"
41 #include "gpu/command_buffer/service/framebuffer_manager.h"
42 #include "gpu/command_buffer/service/gl_utils.h"
43 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
44 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
45 #include "gpu/command_buffer/service/gpu_state_tracer.h"
46 #include "gpu/command_buffer/service/gpu_switches.h"
47 #include "gpu/command_buffer/service/gpu_tracer.h"
48 #include "gpu/command_buffer/service/image_manager.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/program_manager.h"
52 #include "gpu/command_buffer/service/query_manager.h"
53 #include "gpu/command_buffer/service/renderbuffer_manager.h"
54 #include "gpu/command_buffer/service/shader_manager.h"
55 #include "gpu/command_buffer/service/shader_translator.h"
56 #include "gpu/command_buffer/service/shader_translator_cache.h"
57 #include "gpu/command_buffer/service/stream_texture.h"
58 #include "gpu/command_buffer/service/stream_texture_manager.h"
59 #include "gpu/command_buffer/service/texture_manager.h"
60 #include "gpu/command_buffer/service/vertex_array_manager.h"
61 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
62 #include "ui/gl/gl_bindings.h"
63 #include "ui/gl/gl_fence.h"
64 #include "ui/gl/gl_image.h"
65 #include "ui/gl/gl_implementation.h"
66 #include "ui/gl/gl_surface.h"
68 #if defined(OS_MACOSX)
69 #include "ui/gl/io_surface_support_mac.h"
73 #include "base/win/win_util.h"
76 // TODO(zmo): we can't include "City.h" due to type def conflicts.
77 extern uint64 CityHash64(const char*, size_t);
84 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
85 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
86 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
88 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
89 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
90 return static_cast<khronos_uint64_t>(
91 CityHash64(name, static_cast<size_t>(len)));
95 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
98 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
101 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
102 GLenum precision_type,
103 GLint *range, GLint *precision) {
104 switch (precision_type) {
108 // These values are for a 32-bit twos-complement integer format.
114 case GL_MEDIUM_FLOAT:
116 // These values are for an IEEE single-precision floating-point format.
126 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
127 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
128 // This function is sometimes defined even though it's really just
129 // a stub, so we need to set range and precision as if it weren't
130 // defined before calling it.
131 // On Mac OS with some GPUs, calling this generates a
132 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
134 glGetShaderPrecisionFormat(shader_type, precision_type,
137 // TODO(brianderson): Make the following official workarounds.
139 // Some drivers have bugs where they report the ranges as a negative number.
140 // Taking the absolute value here shouldn't hurt because negative numbers
141 // aren't expected anyway.
142 range[0] = abs(range[0]);
143 range[1] = abs(range[1]);
145 // If the driver reports a precision for highp float that isn't actually
146 // highp, don't pretend like it's supported because shader compilation will
148 if (precision_type == GL_HIGH_FLOAT &&
149 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
159 class GLES2DecoderImpl;
161 // Local versions of the SET_GL_ERROR macros
162 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
163 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
164 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
165 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
166 function_name, value, label)
167 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
168 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
169 function_name, pname)
170 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
171 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
173 #define LOCAL_PEEK_GL_ERROR(function_name) \
174 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
175 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
176 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
177 #define LOCAL_PERFORMANCE_WARNING(msg) \
178 PerformanceWarning(__FILE__, __LINE__, msg)
179 #define LOCAL_RENDER_WARNING(msg) \
180 RenderWarning(__FILE__, __LINE__, msg)
182 // Check that certain assumptions the code makes are true. There are places in
183 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
184 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
185 // a few others) are 32bits. If they are not 32bits the code will have to change
186 // to call those GL functions with service side memory and then copy the results
187 // to shared memory, converting the sizes.
188 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
189 GLint_not_same_size_as_uint32);
190 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
191 GLint_not_same_size_as_uint32);
192 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
193 GLfloat_not_same_size_as_float);
195 // TODO(kbr): the use of this anonymous namespace core dumps the
196 // linker on Mac OS X 10.6 when the symbol ordering file is used
199 // Returns the address of the first byte after a struct.
200 template <typename T>
201 const void* AddressAfterStruct(const T& pod) {
202 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
205 // Returns the address of the frst byte after the struct or NULL if size >
206 // immediate_data_size.
207 template <typename RETURN_TYPE, typename COMMAND_TYPE>
208 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
210 uint32 immediate_data_size) {
211 return (size <= immediate_data_size) ?
212 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
216 // Computes the data size for certain gl commands like glUniform.
217 bool ComputeDataSize(
220 unsigned int elements_per_unit,
223 if (!SafeMultiplyUint32(count, size, &value)) {
226 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
233 // A struct to hold info about each command.
235 int arg_flags; // How to handle the arguments for this command
236 int arg_count; // How many arguments are expected for this command.
239 // A table of CommandInfo for all the commands.
240 const CommandInfo g_command_info[] = {
241 #define GLES2_CMD_OP(name) { \
242 cmds::name::kArgFlags, \
243 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
245 GLES2_COMMAND_LIST(GLES2_CMD_OP)
250 // Return true if a character belongs to the ASCII subset as defined in
251 // GLSL ES 1.0 spec section 3.1.
252 static bool CharacterIsValidForGLES(unsigned char c) {
253 // Printing characters are valid except " $ ` @ \ ' DEL.
254 if (c >= 32 && c <= 126 &&
263 // Horizontal tab, line feed, vertical tab, form feed, carriage return
265 if (c >= 9 && c <= 13) {
272 static bool StringIsValidForGLES(const char* str) {
273 for (; *str; ++str) {
274 if (!CharacterIsValidForGLES(*str)) {
281 // Wrapper for glEnable/glDisable that doesn't suck.
282 static void EnableDisable(GLenum pname, bool enable) {
290 // This class prevents any GL errors that occur when it is in scope from
291 // being reported to the client.
292 class ScopedGLErrorSuppressor {
294 explicit ScopedGLErrorSuppressor(
295 const char* function_name, ErrorState* error_state);
296 ~ScopedGLErrorSuppressor();
298 const char* function_name_;
299 ErrorState* error_state_;
300 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
303 // Temporarily changes a decoder's bound 2D texture and restore it when this
304 // object goes out of scope. Also temporarily switches to using active texture
305 // unit zero in case the client has changed that to something invalid.
306 class ScopedTexture2DBinder {
308 ScopedTexture2DBinder(ContextState* state, GLuint id);
309 ~ScopedTexture2DBinder();
312 ContextState* state_;
313 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
316 // Temporarily changes a decoder's bound render buffer and restore it when this
317 // object goes out of scope.
318 class ScopedRenderBufferBinder {
320 ScopedRenderBufferBinder(ContextState* state, GLuint id);
321 ~ScopedRenderBufferBinder();
324 ContextState* state_;
325 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
328 // Temporarily changes a decoder's bound frame buffer and restore it when this
329 // object goes out of scope.
330 class ScopedFrameBufferBinder {
332 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
333 ~ScopedFrameBufferBinder();
336 GLES2DecoderImpl* decoder_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
340 // Temporarily changes a decoder's bound frame buffer to a resolved version of
341 // the multisampled offscreen render buffer if that buffer is multisampled, and,
342 // if it is bound or enforce_internal_framebuffer is true. If internal is
343 // true, the resolved framebuffer is not visible to the parent.
344 class ScopedResolvedFrameBufferBinder {
346 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
347 bool enforce_internal_framebuffer,
349 ~ScopedResolvedFrameBufferBinder();
352 GLES2DecoderImpl* decoder_;
353 bool resolve_and_bind_;
354 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
357 // Encapsulates an OpenGL texture.
360 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
363 // Create a new render texture.
366 // Set the initial size and format of a render texture or resize it.
367 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
369 // Copy the contents of the currently bound frame buffer.
370 void Copy(const gfx::Size& size, GLenum format);
372 // Destroy the render texture. This must be explicitly called before
373 // destroying this object.
376 // Invalidate the texture. This can be used when a context is lost and it is
377 // not possible to make it current in order to free the resource.
384 gfx::Size size() const {
388 size_t estimated_size() const {
389 return memory_tracker_.GetMemRepresented();
393 MemoryTypeTracker memory_tracker_;
394 ContextState* state_;
395 size_t bytes_allocated_;
398 DISALLOW_COPY_AND_ASSIGN(BackTexture);
401 // Encapsulates an OpenGL render buffer of any format.
402 class BackRenderbuffer {
404 explicit BackRenderbuffer(
405 RenderbufferManager* renderbuffer_manager,
406 MemoryTracker* memory_tracker,
407 ContextState* state);
410 // Create a new render buffer.
413 // Set the initial size and format of a render buffer or resize it.
414 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
416 // Destroy the render buffer. This must be explicitly called before destroying
420 // Invalidate the render buffer. This can be used when a context is lost and
421 // it is not possible to make it current in order to free the resource.
428 size_t estimated_size() const {
429 return memory_tracker_.GetMemRepresented();
433 RenderbufferManager* renderbuffer_manager_;
434 MemoryTypeTracker memory_tracker_;
435 ContextState* state_;
436 size_t bytes_allocated_;
438 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
441 // Encapsulates an OpenGL frame buffer.
442 class BackFramebuffer {
444 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
447 // Create a new frame buffer.
450 // Attach a color render buffer to a frame buffer.
451 void AttachRenderTexture(BackTexture* texture);
453 // Attach a render buffer to a frame buffer. Note that this unbinds any
454 // currently bound frame buffer.
455 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
457 // Destroy the frame buffer. This must be explicitly called before destroying
461 // Invalidate the frame buffer. This can be used when a context is lost and it
462 // is not possible to make it current in order to free the resource.
465 // See glCheckFramebufferStatusEXT.
466 GLenum CheckStatus();
473 GLES2DecoderImpl* decoder_;
475 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
478 struct FenceCallback {
479 explicit FenceCallback()
480 : fence(gfx::GLFence::Create()) {
483 void AddCallback(base::Closure cb) {
484 callbacks.push_back(cb);
486 std::vector<base::Closure> callbacks;
487 scoped_ptr<gfx::GLFence> fence;
491 // } // anonymous namespace.
493 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
494 uint32* service_texture_id) {
498 GLES2Decoder::GLES2Decoder()
499 : initialized_(false),
501 log_commands_(false) {
504 GLES2Decoder::~GLES2Decoder() {
507 bool GLES2Decoder::testing_force_is_angle_;
509 void GLES2Decoder::set_testing_force_is_angle(bool force) {
510 testing_force_is_angle_ = force;
513 bool GLES2Decoder::IsAngle() {
515 return testing_force_is_angle_ ||
516 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
518 return testing_force_is_angle_;
522 // This class implements GLES2Decoder so we don't have to expose all the GLES2
523 // cmd stuff to outside this class.
524 class GLES2DecoderImpl : public GLES2Decoder,
525 public FramebufferManager::TextureDetachObserver {
527 // Used by PrepForSetUniformByLocation to validate types.
528 struct BaseUniformInfo {
529 const GLenum* const valid_types;
530 size_t num_valid_types;
533 explicit GLES2DecoderImpl(ContextGroup* group);
534 virtual ~GLES2DecoderImpl();
536 // Overridden from AsyncAPIInterface.
537 virtual Error DoCommand(unsigned int command,
538 unsigned int arg_count,
539 const void* args) OVERRIDE;
541 // Overridden from AsyncAPIInterface.
542 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
544 // Overridden from GLES2Decoder.
545 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
546 const scoped_refptr<gfx::GLContext>& context,
548 const gfx::Size& size,
549 const DisallowedFeatures& disallowed_features,
550 const std::vector<int32>& attribs) OVERRIDE;
551 virtual void Destroy(bool have_context) OVERRIDE;
552 virtual void SetSurface(
553 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
554 virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
555 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
556 void UpdateParentTextureInfo();
557 virtual bool MakeCurrent() OVERRIDE;
558 virtual void ReleaseCurrent() OVERRIDE;
559 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
560 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
561 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
562 virtual void RestoreState() const OVERRIDE;
564 virtual void RestoreActiveTexture() const OVERRIDE {
565 state_.RestoreActiveTexture();
567 virtual void RestoreAllTextureUnitBindings() const OVERRIDE {
568 state_.RestoreAllTextureUnitBindings();
570 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
571 state_.RestoreAttribute(index);
573 virtual void RestoreBufferBindings() const OVERRIDE {
574 state_.RestoreBufferBindings();
576 virtual void RestoreGlobalState() const OVERRIDE {
577 state_.RestoreGlobalState();
579 virtual void RestoreProgramBindings() const OVERRIDE {
580 state_.RestoreProgramBindings();
582 virtual void RestoreRenderbufferBindings() const OVERRIDE {
583 state_.RestoreRenderbufferBindings();
585 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
586 state_.RestoreTextureUnitBindings(unit);
588 virtual void RestoreFramebufferBindings() const OVERRIDE;
589 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
591 virtual QueryManager* GetQueryManager() OVERRIDE {
592 return query_manager_.get();
594 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
595 return vertex_array_manager_.get();
597 virtual bool ProcessPendingQueries() OVERRIDE;
598 virtual bool HasMoreIdleWork() OVERRIDE;
599 virtual void PerformIdleWork() OVERRIDE;
601 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
603 virtual void SetResizeCallback(
604 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
606 virtual Logger* GetLogger() OVERRIDE;
607 virtual ErrorState* GetErrorState() OVERRIDE;
609 virtual void SetShaderCacheCallback(
610 const ShaderCacheCallback& callback) OVERRIDE;
611 virtual void SetWaitSyncPointCallback(
612 const WaitSyncPointCallback& callback) OVERRIDE;
614 virtual AsyncPixelTransferManager*
615 GetAsyncPixelTransferManager() OVERRIDE;
616 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
617 virtual void SetAsyncPixelTransferManagerForTest(
618 AsyncPixelTransferManager* manager) OVERRIDE;
619 void ProcessFinishedAsyncTransfers();
621 virtual bool GetServiceTextureId(uint32 client_texture_id,
622 uint32* service_texture_id) OVERRIDE;
624 virtual uint32 GetTextureUploadCount() OVERRIDE;
625 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
626 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
627 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
629 // Restores the current state to the user's settings.
630 void RestoreCurrentFramebufferBindings();
632 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
633 void ApplyDirtyState();
635 // These check the state of the currently bound framebuffer or the
636 // backbuffer if no framebuffer is bound.
637 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
638 // check with all attached and enabled color attachments.
639 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
640 bool BoundFramebufferHasDepthAttachment();
641 bool BoundFramebufferHasStencilAttachment();
643 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
645 // Overridden from FramebufferManager::TextureDetachObserver:
646 virtual void OnTextureRefDetachedFromFramebuffer(
647 TextureRef* texture) OVERRIDE;
650 friend class ScopedFrameBufferBinder;
651 friend class ScopedResolvedFrameBufferBinder;
652 friend class BackFramebuffer;
654 // Initialize or re-initialize the shader translator.
655 bool InitializeShaderTranslator();
657 void UpdateCapabilities();
659 // Helpers for the glGen and glDelete functions.
660 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
661 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
662 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
663 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
664 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
665 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
666 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
667 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
668 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
669 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
670 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
671 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
674 void OnFboChanged() const;
675 void OnUseFramebuffer() const;
677 // TODO(gman): Cache these pointers?
678 BufferManager* buffer_manager() {
679 return group_->buffer_manager();
682 RenderbufferManager* renderbuffer_manager() {
683 return group_->renderbuffer_manager();
686 FramebufferManager* framebuffer_manager() {
687 return group_->framebuffer_manager();
690 ProgramManager* program_manager() {
691 return group_->program_manager();
694 ShaderManager* shader_manager() {
695 return group_->shader_manager();
698 const TextureManager* texture_manager() const {
699 return group_->texture_manager();
702 TextureManager* texture_manager() {
703 return group_->texture_manager();
706 MailboxManager* mailbox_manager() {
707 return group_->mailbox_manager();
710 ImageManager* image_manager() {
711 return group_->image_manager();
714 VertexArrayManager* vertex_array_manager() {
715 return vertex_array_manager_.get();
718 MemoryTracker* memory_tracker() {
719 return group_->memory_tracker();
722 StreamTextureManager* stream_texture_manager() const {
723 return group_->stream_texture_manager();
726 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
727 MemoryTracker* tracker = memory_tracker();
729 return tracker->EnsureGPUMemoryAvailable(estimated_size);
734 bool IsOffscreenBufferMultisampled() const {
735 return offscreen_target_samples_ > 1;
738 // Creates a Texture for the given texture.
739 TextureRef* CreateTexture(
740 GLuint client_id, GLuint service_id) {
741 return texture_manager()->CreateTexture(client_id, service_id);
744 // Gets the texture info for the given texture. Returns NULL if none exists.
745 TextureRef* GetTexture(GLuint client_id) const {
746 return texture_manager()->GetTexture(client_id);
749 // Deletes the texture info for the given texture.
750 void RemoveTexture(GLuint client_id) {
751 texture_manager()->RemoveTexture(client_id);
754 // Get the size (in pixels) of the currently bound frame buffer (either FBO
755 // or regular back buffer).
756 gfx::Size GetBoundReadFrameBufferSize();
758 // Get the format of the currently bound frame buffer (either FBO or regular
760 GLenum GetBoundReadFrameBufferInternalFormat();
761 GLenum GetBoundDrawFrameBufferInternalFormat();
763 // Wrapper for CompressedTexImage2D commands.
764 error::Error DoCompressedTexImage2D(
767 GLenum internal_format,
774 // Wrapper for CompressedTexSubImage2D.
775 void DoCompressedTexSubImage2D(
786 // Wrapper for CopyTexImage2D.
787 void DoCopyTexImage2D(
790 GLenum internal_format,
797 // Wrapper for SwapBuffers.
798 void DoSwapBuffers();
800 // Wrapper for CopyTexSubImage2D.
801 void DoCopyTexSubImage2D(
811 // Validation for TexSubImage2D.
812 bool ValidateTexSubImage2D(
814 const char* function_name,
825 // Wrapper for TexSubImage2D.
826 error::Error DoTexSubImage2D(
837 // Extra validation for async tex(Sub)Image2D.
838 bool ValidateAsyncTransfer(
839 const char* function_name,
840 TextureRef* texture_ref,
845 // Wrapper for TexImageIOSurface2DCHROMIUM.
846 void DoTexImageIOSurface2DCHROMIUM(
850 GLuint io_surface_id,
853 void DoCopyTextureCHROMIUM(
858 GLenum internal_format,
861 // Wrapper for TexStorage2DEXT.
862 void DoTexStorage2DEXT(
865 GLenum internal_format,
869 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
870 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
872 void DoBindTexImage2DCHROMIUM(
875 void DoReleaseTexImage2DCHROMIUM(
879 void DoTraceEndCHROMIUM(void);
881 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
883 // Creates a Program for the given program.
884 Program* CreateProgram(
885 GLuint client_id, GLuint service_id) {
886 return program_manager()->CreateProgram(client_id, service_id);
889 // Gets the program info for the given program. Returns NULL if none exists.
890 Program* GetProgram(GLuint client_id) {
891 return program_manager()->GetProgram(client_id);
895 void LogClientServiceMapping(
896 const char* /* function_name */,
897 GLuint /* client_id */,
898 GLuint /* service_id */) {
901 void LogClientServiceForInfo(
902 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
905 void LogClientServiceMapping(
906 const char* function_name, GLuint client_id, GLuint service_id) {
907 if (service_logging_) {
908 DLOG(INFO) << "[" << logger_.GetLogPrefix() << "] " << function_name
909 << ": client_id = " << client_id
910 << ", service_id = " << service_id;
914 void LogClientServiceForInfo(
915 T* info, GLuint client_id, const char* function_name) {
917 LogClientServiceMapping(function_name, client_id, info->service_id());
922 // Gets the program info for the given program. If it's not a program
923 // generates a GL error. Returns NULL if not program.
924 Program* GetProgramInfoNotShader(
925 GLuint client_id, const char* function_name) {
926 Program* program = GetProgram(client_id);
928 if (GetShader(client_id)) {
930 GL_INVALID_OPERATION, function_name, "shader passed for program");
932 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
935 LogClientServiceForInfo(program, client_id, function_name);
940 // Creates a Shader for the given shader.
941 Shader* CreateShader(
944 GLenum shader_type) {
945 return shader_manager()->CreateShader(
946 client_id, service_id, shader_type);
949 // Gets the shader info for the given shader. Returns NULL if none exists.
950 Shader* GetShader(GLuint client_id) {
951 return shader_manager()->GetShader(client_id);
954 // Gets the shader info for the given shader. If it's not a shader generates a
955 // GL error. Returns NULL if not shader.
956 Shader* GetShaderInfoNotProgram(
957 GLuint client_id, const char* function_name) {
958 Shader* shader = GetShader(client_id);
960 if (GetProgram(client_id)) {
962 GL_INVALID_OPERATION, function_name, "program passed for shader");
965 GL_INVALID_VALUE, function_name, "unknown shader");
968 LogClientServiceForInfo(shader, client_id, function_name);
972 // Creates a buffer info for the given buffer.
973 void CreateBuffer(GLuint client_id, GLuint service_id) {
974 return buffer_manager()->CreateBuffer(client_id, service_id);
977 // Gets the buffer info for the given buffer.
978 Buffer* GetBuffer(GLuint client_id) {
979 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
983 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
984 // on glDeleteBuffers so we can make sure the user does not try to render
985 // with deleted buffers.
986 void RemoveBuffer(GLuint client_id);
988 // Creates a framebuffer info for the given framebuffer.
989 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
990 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
993 // Gets the framebuffer info for the given framebuffer.
994 Framebuffer* GetFramebuffer(GLuint client_id) {
995 return framebuffer_manager()->GetFramebuffer(client_id);
998 // Removes the framebuffer info for the given framebuffer.
999 void RemoveFramebuffer(GLuint client_id) {
1000 framebuffer_manager()->RemoveFramebuffer(client_id);
1003 // Creates a renderbuffer info for the given renderbuffer.
1004 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1005 return renderbuffer_manager()->CreateRenderbuffer(
1006 client_id, service_id);
1009 // Gets the renderbuffer info for the given renderbuffer.
1010 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1011 return renderbuffer_manager()->GetRenderbuffer(client_id);
1014 // Removes the renderbuffer info for the given renderbuffer.
1015 void RemoveRenderbuffer(GLuint client_id) {
1016 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1019 // Gets the vertex attrib manager for the given vertex array.
1020 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1021 VertexAttribManager* info =
1022 vertex_array_manager()->GetVertexAttribManager(client_id);
1026 // Removes the vertex attrib manager for the given vertex array.
1027 void RemoveVertexAttribManager(GLuint client_id) {
1028 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1031 // Creates a vertex attrib manager for the given vertex array.
1032 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1033 return vertex_array_manager()->CreateVertexAttribManager(
1034 client_id, service_id, group_->max_vertex_attribs());
1037 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1038 void DoBindUniformLocationCHROMIUM(
1039 GLuint client_id, GLint location, const char* name);
1041 error::Error GetAttribLocationHelper(
1042 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1043 const std::string& name_str);
1045 error::Error GetUniformLocationHelper(
1046 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1047 const std::string& name_str);
1049 // Helper for glShaderSource.
1050 error::Error ShaderSourceHelper(
1051 GLuint client_id, const char* data, uint32 data_size);
1053 // Clear any textures used by the current program.
1054 bool ClearUnclearedTextures();
1056 // Clear any uncleared level in texture.
1057 // Returns false if there was a generated GL error.
1058 bool ClearTexture(Texture* texture);
1060 // Clears any uncleared attachments attached to the given frame buffer.
1061 // Returns false if there was a generated GL error.
1062 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1064 // overridden from GLES2Decoder
1065 virtual bool ClearLevel(unsigned service_id,
1066 unsigned bind_target,
1073 bool is_texture_immutable) OVERRIDE;
1075 // Restore all GL state that affects clearing.
1076 void RestoreClearState();
1078 // Remembers the state of some capabilities.
1079 // Returns: true if glEnable/glDisable should actually be called.
1080 bool SetCapabilityState(GLenum cap, bool enabled);
1082 // Check that the currently bound framebuffers are valid.
1083 // Generates GL error if not.
1084 bool CheckBoundFramebuffersValid(const char* func_name);
1086 // Check if a framebuffer meets our requirements.
1087 bool CheckFramebufferValid(
1088 Framebuffer* framebuffer,
1090 const char* func_name);
1092 // Checks if the current program exists and is valid. If not generates the
1093 // appropriate GL error. Returns true if the current program is in a usable
1095 bool CheckCurrentProgram(const char* function_name);
1097 // Checks if the current program exists and is valid and that location is not
1098 // -1. If the current program is not valid generates the appropriate GL
1099 // error. Returns true if the current program is in a usable state and
1100 // location is not -1.
1101 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1103 // Gets the type of a uniform for a location in the current program. Sets GL
1104 // errors if the current program is not valid. Returns true if the current
1105 // program is valid and the location exists. Adjusts count so it
1106 // does not overflow the uniform.
1107 bool PrepForSetUniformByLocation(
1108 GLint fake_location, const char* function_name,
1109 const BaseUniformInfo& base_info,
1110 GLint* real_location, GLenum* type, GLsizei* count);
1112 // Gets the service id for any simulated backbuffer fbo.
1113 GLuint GetBackbufferServiceId() const;
1115 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1116 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1118 // Helper for glGetVertexAttrib
1119 void GetVertexAttribHelper(
1120 const VertexAttrib* attrib, GLenum pname, GLint* param);
1122 // Wrapper for glCreateProgram
1123 bool CreateProgramHelper(GLuint client_id);
1125 // Wrapper for glCreateShader
1126 bool CreateShaderHelper(GLenum type, GLuint client_id);
1128 // Wrapper for glActiveTexture
1129 void DoActiveTexture(GLenum texture_unit);
1131 // Wrapper for glAttachShader
1132 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1134 // Wrapper for glBindBuffer since we need to track the current targets.
1135 void DoBindBuffer(GLenum target, GLuint buffer);
1137 // Wrapper for glBindFramebuffer since we need to track the current targets.
1138 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1140 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1141 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1143 // Wrapper for glBindTexture since we need to track the current targets.
1144 void DoBindTexture(GLenum target, GLuint texture);
1146 // Wrapper for glBindVertexArrayOES
1147 void DoBindVertexArrayOES(GLuint array);
1148 void EmulateVertexArrayState();
1150 // Wrapper for glBlitFramebufferEXT.
1151 void DoBlitFramebufferEXT(
1152 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1153 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1154 GLbitfield mask, GLenum filter);
1156 // Wrapper for glBufferSubData.
1157 void DoBufferSubData(
1158 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1160 // Wrapper for glCheckFramebufferStatus
1161 GLenum DoCheckFramebufferStatus(GLenum target);
1163 // Wrapper for glClear
1164 error::Error DoClear(GLbitfield mask);
1166 // Wrappers for various state.
1167 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1168 void DoSampleCoverage(GLclampf value, GLboolean invert);
1170 // Wrapper for glCompileShader.
1171 void DoCompileShader(GLuint shader);
1173 // Helper for DeleteSharedIdsCHROMIUM commands.
1174 void DoDeleteSharedIdsCHROMIUM(
1175 GLuint namespace_id, GLsizei n, const GLuint* ids);
1177 // Wrapper for glDetachShader
1178 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1180 // Wrapper for glDisable
1181 void DoDisable(GLenum cap);
1183 // Wrapper for glDisableVertexAttribArray.
1184 void DoDisableVertexAttribArray(GLuint index);
1186 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1188 void DoDiscardFramebufferEXT(GLenum target,
1189 GLsizei numAttachments,
1190 const GLenum* attachments);
1192 // Wrapper for glEnable
1193 void DoEnable(GLenum cap);
1195 // Wrapper for glEnableVertexAttribArray.
1196 void DoEnableVertexAttribArray(GLuint index);
1198 // Wrapper for glFinish.
1201 // Wrapper for glFlush.
1204 // Wrapper for glFramebufferRenderbufffer.
1205 void DoFramebufferRenderbuffer(
1206 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1207 GLuint renderbuffer);
1209 // Wrapper for glFramebufferTexture2D.
1210 void DoFramebufferTexture2D(
1211 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1214 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1215 void DoFramebufferTexture2DMultisample(
1216 GLenum target, GLenum attachment, GLenum textarget,
1217 GLuint texture, GLint level, GLsizei samples);
1219 // Common implementation for both DoFramebufferTexture2D wrappers.
1220 void DoFramebufferTexture2DCommon(const char* name,
1221 GLenum target, GLenum attachment, GLenum textarget,
1222 GLuint texture, GLint level, GLsizei samples);
1224 // Wrapper for glGenerateMipmap
1225 void DoGenerateMipmap(GLenum target);
1227 // Helper for GenSharedIdsCHROMIUM commands.
1228 void DoGenSharedIdsCHROMIUM(
1229 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1231 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1232 // to account for different pname values defined in different extension
1234 GLenum AdjustGetPname(GLenum pname);
1236 // Wrapper for DoGetBooleanv.
1237 void DoGetBooleanv(GLenum pname, GLboolean* params);
1239 // Wrapper for DoGetFloatv.
1240 void DoGetFloatv(GLenum pname, GLfloat* params);
1242 // Wrapper for glGetFramebufferAttachmentParameteriv.
1243 void DoGetFramebufferAttachmentParameteriv(
1244 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1246 // Wrapper for glGetIntegerv.
1247 void DoGetIntegerv(GLenum pname, GLint* params);
1249 // Gets the max value in a range in a buffer.
1250 GLuint DoGetMaxValueInBufferCHROMIUM(
1251 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1253 // Wrapper for glGetBufferParameteriv.
1254 void DoGetBufferParameteriv(
1255 GLenum target, GLenum pname, GLint* params);
1257 // Wrapper for glGetProgramiv.
1258 void DoGetProgramiv(
1259 GLuint program_id, GLenum pname, GLint* params);
1261 // Wrapper for glRenderbufferParameteriv.
1262 void DoGetRenderbufferParameteriv(
1263 GLenum target, GLenum pname, GLint* params);
1265 // Wrapper for glGetShaderiv
1266 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1268 // Wrappers for glGetVertexAttrib.
1269 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1270 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1272 // Wrappers for glIsXXX functions.
1273 bool DoIsEnabled(GLenum cap);
1274 bool DoIsBuffer(GLuint client_id);
1275 bool DoIsFramebuffer(GLuint client_id);
1276 bool DoIsProgram(GLuint client_id);
1277 bool DoIsRenderbuffer(GLuint client_id);
1278 bool DoIsShader(GLuint client_id);
1279 bool DoIsTexture(GLuint client_id);
1280 bool DoIsVertexArrayOES(GLuint client_id);
1282 // Wrapper for glLinkProgram
1283 void DoLinkProgram(GLuint program);
1285 // Helper for RegisterSharedIdsCHROMIUM.
1286 void DoRegisterSharedIdsCHROMIUM(
1287 GLuint namespace_id, GLsizei n, const GLuint* ids);
1289 // Wrapper for glRenderbufferStorage.
1290 void DoRenderbufferStorage(
1291 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1293 // Wrapper for glRenderbufferStorageMultisampleEXT.
1294 void DoRenderbufferStorageMultisample(
1295 GLenum target, GLsizei samples, GLenum internalformat,
1296 GLsizei width, GLsizei height);
1298 // Verifies that the currently bound multisample renderbuffer is valid
1299 // Very slow! Only done on platforms with driver bugs that return invalid
1300 // buffers under memory pressure
1301 bool VerifyMultisampleRenderbufferIntegrity(
1302 GLuint renderbuffer, GLenum format);
1304 // Wrapper for glReleaseShaderCompiler.
1305 void DoReleaseShaderCompiler() { }
1307 // Wrappers for glTexParameter functions.
1308 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1309 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1310 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1311 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1313 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1314 // spec only these 2 functions can be used to set sampler uniforms.
1315 void DoUniform1i(GLint fake_location, GLint v0);
1316 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1317 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1318 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1319 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1321 // Wrappers for glUniformfv because some drivers don't correctly accept
1323 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1324 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1325 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1326 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1328 void DoUniformMatrix2fv(
1329 GLint fake_location, GLsizei count, GLboolean transpose,
1330 const GLfloat* value);
1331 void DoUniformMatrix3fv(
1332 GLint fake_location, GLsizei count, GLboolean transpose,
1333 const GLfloat* value);
1334 void DoUniformMatrix4fv(
1335 GLint fake_location, GLsizei count, GLboolean transpose,
1336 const GLfloat* value);
1338 bool SetVertexAttribValue(
1339 const char* function_name, GLuint index, const GLfloat* value);
1341 // Wrappers for glVertexAttrib??
1342 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1343 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1344 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1345 void DoVertexAttrib4f(
1346 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1347 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1348 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1349 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1350 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1352 // Wrapper for glViewport
1353 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1355 // Wrapper for glUseProgram
1356 void DoUseProgram(GLuint program);
1358 // Wrapper for glValidateProgram.
1359 void DoValidateProgram(GLuint program_client_id);
1361 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1362 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1363 void DoPopGroupMarkerEXT(void);
1365 // Gets the number of values that will be returned by glGetXXX. Returns
1366 // false if pname is unknown.
1367 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1369 // Checks if the current program and vertex attributes are valid for drawing.
1371 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1373 // Returns true if successful, simulated will be true if attrib0 was
1375 bool SimulateAttrib0(
1376 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1377 void RestoreStateForAttrib(GLuint attrib);
1379 // If texture is a stream texture, this will update the stream to the newest
1380 // buffer and bind the texture implicitly.
1381 void UpdateStreamTextureIfNeeded(Texture* texture, GLuint texture_unit_index);
1383 // If an image is bound to texture, this will call Will/DidUseTexImage
1385 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1386 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1388 // Returns false if textures were replaced.
1389 bool PrepareTexturesForRender();
1390 void RestoreStateForTextures();
1392 // Returns true if GL_FIXED attribs were simulated.
1393 bool SimulateFixedAttribs(
1394 const char* function_name,
1395 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1396 void RestoreStateForSimulatedFixedAttribs();
1398 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1399 // cases (primcount is 0 for non-instanced).
1400 error::Error DoDrawArrays(
1401 const char* function_name,
1402 bool instanced, GLenum mode, GLint first, GLsizei count,
1404 error::Error DoDrawElements(
1405 const char* function_name,
1406 bool instanced, GLenum mode, GLsizei count, GLenum type,
1407 int32 offset, GLsizei primcount);
1409 GLenum GetBindTargetForSamplerType(GLenum type) {
1410 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1411 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1414 return GL_TEXTURE_2D;
1415 case GL_SAMPLER_CUBE:
1416 return GL_TEXTURE_CUBE_MAP;
1417 case GL_SAMPLER_EXTERNAL_OES:
1418 return GL_TEXTURE_EXTERNAL_OES;
1419 case GL_SAMPLER_2D_RECT_ARB:
1420 return GL_TEXTURE_RECTANGLE_ARB;
1427 // Gets the framebuffer info for a particular target.
1428 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1429 Framebuffer* framebuffer = NULL;
1431 case GL_FRAMEBUFFER:
1432 case GL_DRAW_FRAMEBUFFER_EXT:
1433 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1435 case GL_READ_FRAMEBUFFER_EXT:
1436 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1445 Renderbuffer* GetRenderbufferInfoForTarget(
1447 Renderbuffer* renderbuffer = NULL;
1449 case GL_RENDERBUFFER:
1450 renderbuffer = state_.bound_renderbuffer.get();
1456 return renderbuffer;
1459 // Validates the program and location for a glGetUniform call and returns
1460 // a SizeResult setup to receive the result. Returns true if glGetUniform
1461 // should be called.
1462 bool GetUniformSetup(
1463 GLuint program, GLint fake_location,
1464 uint32 shm_id, uint32 shm_offset,
1465 error::Error* error, GLint* real_location, GLuint* service_id,
1466 void** result, GLenum* result_type);
1468 // Computes the estimated memory used for the backbuffer and passes it to
1469 // the tracing system.
1470 size_t GetBackbufferMemoryTotal();
1472 virtual bool WasContextLost() OVERRIDE;
1473 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1474 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1476 #if defined(OS_MACOSX)
1477 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1480 // Validates the combination of texture parameters. For example validates that
1481 // for a given format the specific type, level and targets are valid.
1482 // Synthesizes the correct GL error if invalid. Returns true if valid.
1483 bool ValidateTextureParameters(
1484 const char* function_name,
1485 GLenum target, GLenum format, GLenum type, GLint level);
1487 bool ValidateCompressedTexDimensions(
1488 const char* function_name,
1489 GLint level, GLsizei width, GLsizei height, GLenum format);
1490 bool ValidateCompressedTexFuncData(
1491 const char* function_name,
1492 GLsizei width, GLsizei height, GLenum format, size_t size);
1493 bool ValidateCompressedTexSubDimensions(
1494 const char* function_name,
1495 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1496 GLsizei width, GLsizei height, GLenum format,
1499 void RenderWarning(const char* filename, int line, const std::string& msg);
1500 void PerformanceWarning(
1501 const char* filename, int line, const std::string& msg);
1503 const FeatureInfo::FeatureFlags& features() const {
1504 return feature_info_->feature_flags();
1507 const FeatureInfo::Workarounds& workarounds() const {
1508 return feature_info_->workarounds();
1511 bool ShouldDeferDraws() {
1512 return !offscreen_target_frame_buffer_.get() &&
1513 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1514 surface_->DeferDraws();
1517 bool ShouldDeferReads() {
1518 return !offscreen_target_frame_buffer_.get() &&
1519 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1520 surface_->DeferDraws();
1523 void ProcessPendingReadPixels();
1524 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1526 // Generate a member function prototype for each command in an automated and
1528 #define GLES2_CMD_OP(name) \
1529 Error Handle ## name( \
1530 uint32 immediate_data_size, \
1531 const cmds::name& args); \
1533 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1537 // The GL context this decoder renders to on behalf of the client.
1538 scoped_refptr<gfx::GLSurface> surface_;
1539 scoped_refptr<gfx::GLContext> context_;
1541 // The ContextGroup for this decoder uses to track resources.
1542 scoped_refptr<ContextGroup> group_;
1544 DebugMarkerManager debug_marker_manager_;
1547 // All the state for this context.
1548 ContextState state_;
1550 // Current width and height of the offscreen frame buffer.
1551 gfx::Size offscreen_size_;
1553 // Util to help with GL.
1556 // unpack flip y as last set by glPixelStorei
1557 bool unpack_flip_y_;
1559 // unpack (un)premultiply alpha as last set by glPixelStorei
1560 bool unpack_premultiply_alpha_;
1561 bool unpack_unpremultiply_alpha_;
1563 // Default vertex attribs manager, used when no VAOs are bound.
1564 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
1566 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1567 GLuint attrib_0_buffer_id_;
1569 // The value currently in attrib_0.
1570 Vec4 attrib_0_value_;
1572 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1573 bool attrib_0_buffer_matches_value_;
1575 // The size of attrib 0.
1576 GLsizei attrib_0_size_;
1578 // The buffer used to simulate GL_FIXED attribs.
1579 GLuint fixed_attrib_buffer_id_;
1581 // The size of fiixed attrib buffer.
1582 GLsizei fixed_attrib_buffer_size_;
1584 // The offscreen frame buffer that the client renders to. With EGL, the
1585 // depth and stencil buffers are separate. With regular GL there is a single
1586 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1587 // offscreen_target_stencil_render_buffer_ is unused.
1588 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1589 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1590 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1591 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1592 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1593 GLenum offscreen_target_color_format_;
1594 GLenum offscreen_target_depth_format_;
1595 GLenum offscreen_target_stencil_format_;
1596 GLsizei offscreen_target_samples_;
1597 GLboolean offscreen_target_buffer_preserved_;
1599 // The copy that is saved when SwapBuffers is called.
1600 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1601 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1602 scoped_refptr<TextureRef>
1603 offscreen_saved_color_texture_info_;
1605 // The copy that is used as the destination for multi-sample resolves.
1606 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1607 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1608 GLenum offscreen_saved_color_format_;
1610 scoped_ptr<QueryManager> query_manager_;
1612 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1614 base::Callback<void(gfx::Size, float)> resize_callback_;
1616 WaitSyncPointCallback wait_sync_point_callback_;
1618 ShaderCacheCallback shader_cache_callback_;
1620 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1622 // The format of the back buffer_
1623 GLenum back_buffer_color_format_;
1624 bool back_buffer_has_depth_;
1625 bool back_buffer_has_stencil_;
1627 // Backbuffer attachments that are currently undefined.
1628 uint32 backbuffer_needs_clear_bits_;
1630 // The current decoder error.
1631 error::Error current_decoder_error_;
1633 bool use_shader_translator_;
1634 scoped_refptr<ShaderTranslator> vertex_translator_;
1635 scoped_refptr<ShaderTranslator> fragment_translator_;
1637 DisallowedFeatures disallowed_features_;
1639 // Cached from ContextGroup
1640 const Validators* validators_;
1641 scoped_refptr<FeatureInfo> feature_info_;
1645 bool has_robustness_extension_;
1646 GLenum reset_status_;
1647 bool reset_by_robustness_extension_;
1649 // These flags are used to override the state of the shared feature_info_
1650 // member. Because the same FeatureInfo instance may be shared among many
1651 // contexts, the assumptions on the availablity of extensions in WebGL
1652 // contexts may be broken. These flags override the shared state to preserve
1654 bool force_webgl_glsl_validation_;
1655 bool derivatives_explicitly_enabled_;
1656 bool frag_depth_explicitly_enabled_;
1657 bool draw_buffers_explicitly_enabled_;
1659 bool compile_shader_always_succeeds_;
1662 bool service_logging_;
1664 #if defined(OS_MACOSX)
1665 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1666 TextureToIOSurfaceMap texture_to_io_surface_map_;
1669 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1671 // Cached values of the currently assigned viewport dimensions.
1672 GLsizei viewport_max_width_;
1673 GLsizei viewport_max_height_;
1675 // Command buffer stats.
1676 base::TimeDelta total_processing_commands_time_;
1678 // States related to each manager.
1679 DecoderTextureState texture_state_;
1680 DecoderFramebufferState framebuffer_state_;
1682 scoped_ptr<GPUTracer> gpu_tracer_;
1683 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1685 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1687 // Used to validate multisample renderbuffers if needed
1688 GLuint validation_texture_;
1689 GLuint validation_fbo_multisample_;
1690 GLuint validation_fbo_;
1692 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1695 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1696 const char* function_name, ErrorState* error_state)
1697 : function_name_(function_name),
1698 error_state_(error_state) {
1699 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1702 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1703 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1706 static void RestoreCurrentTexture2DBindings(ContextState* state) {
1707 TextureUnit& info = state->texture_units[0];
1709 if (info.bound_texture_2d.get()) {
1710 last_id = info.bound_texture_2d->service_id();
1715 glBindTexture(GL_TEXTURE_2D, last_id);
1716 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1719 ScopedTexture2DBinder::ScopedTexture2DBinder(ContextState* state,
1722 ScopedGLErrorSuppressor suppressor(
1723 "ScopedTexture2DBinder::ctor", state_->GetErrorState());
1725 // TODO(apatrick): Check if there are any other states that need to be reset
1726 // before binding a new texture.
1727 glActiveTexture(GL_TEXTURE0);
1728 glBindTexture(GL_TEXTURE_2D, id);
1731 ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1732 ScopedGLErrorSuppressor suppressor(
1733 "ScopedTexture2DBinder::dtor", state_->GetErrorState());
1734 RestoreCurrentTexture2DBindings(state_);
1737 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1740 ScopedGLErrorSuppressor suppressor(
1741 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1742 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1745 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1746 ScopedGLErrorSuppressor suppressor(
1747 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1748 state_->RestoreRenderbufferBindings();
1751 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1753 : decoder_(decoder) {
1754 ScopedGLErrorSuppressor suppressor(
1755 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1756 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1757 decoder->OnFboChanged();
1760 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1761 ScopedGLErrorSuppressor suppressor(
1762 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1763 decoder_->RestoreCurrentFramebufferBindings();
1766 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1767 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1768 : decoder_(decoder) {
1769 resolve_and_bind_ = (
1770 decoder_->offscreen_target_frame_buffer_.get() &&
1771 decoder_->IsOffscreenBufferMultisampled() &&
1772 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1773 enforce_internal_framebuffer));
1774 if (!resolve_and_bind_)
1777 ScopedGLErrorSuppressor suppressor(
1778 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1779 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1780 decoder_->offscreen_target_frame_buffer_->id());
1783 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1784 decoder_->offscreen_resolved_frame_buffer_.reset(
1785 new BackFramebuffer(decoder_));
1786 decoder_->offscreen_resolved_frame_buffer_->Create();
1787 decoder_->offscreen_resolved_color_texture_.reset(
1788 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1789 decoder_->offscreen_resolved_color_texture_->Create();
1791 DCHECK(decoder_->offscreen_saved_color_format_);
1792 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1793 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1795 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1796 decoder_->offscreen_resolved_color_texture_.get());
1797 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1798 GL_FRAMEBUFFER_COMPLETE) {
1799 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1800 << "because offscreen resolved FBO was incomplete.";
1804 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1806 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1808 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1809 const int width = decoder_->offscreen_size_.width();
1810 const int height = decoder_->offscreen_size_.height();
1811 glDisable(GL_SCISSOR_TEST);
1812 if (GLES2Decoder::IsAngle()) {
1813 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1814 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1816 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1817 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1819 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1822 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1823 if (!resolve_and_bind_)
1826 ScopedGLErrorSuppressor suppressor(
1827 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1828 decoder_->RestoreCurrentFramebufferBindings();
1829 if (decoder_->state_.enable_flags.scissor_test) {
1830 glEnable(GL_SCISSOR_TEST);
1834 BackTexture::BackTexture(
1835 MemoryTracker* memory_tracker,
1836 ContextState* state)
1837 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1839 bytes_allocated_(0),
1843 BackTexture::~BackTexture() {
1844 // This does not destroy the render texture because that would require that
1845 // the associated GL context was current. Just check that it was explicitly
1850 void BackTexture::Create() {
1851 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1852 state_->GetErrorState());
1854 glGenTextures(1, &id_);
1855 ScopedTexture2DBinder binder(state_, id_);
1856 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1857 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1858 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1861 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1862 // never called on an offscreen context, no data will ever be uploaded to the
1863 // saved offscreen color texture (it is deferred until to when SwapBuffers
1864 // is called). My idea is that some nvidia drivers might have a bug where
1865 // deleting a texture that has never been populated might cause a
1868 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1870 bytes_allocated_ = 16u * 16u * 4u;
1871 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1874 bool BackTexture::AllocateStorage(
1875 const gfx::Size& size, GLenum format, bool zero) {
1877 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
1878 state_->GetErrorState());
1879 ScopedTexture2DBinder binder(state_, id_);
1880 uint32 image_size = 0;
1881 GLES2Util::ComputeImageDataSizes(
1882 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1885 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1889 scoped_ptr<char[]> zero_data;
1891 zero_data.reset(new char[image_size]);
1892 memset(zero_data.get(), 0, image_size);
1895 glTexImage2D(GL_TEXTURE_2D,
1907 bool success = glGetError() == GL_NO_ERROR;
1909 memory_tracker_.TrackMemFree(bytes_allocated_);
1910 bytes_allocated_ = image_size;
1911 memory_tracker_.TrackMemAlloc(bytes_allocated_);
1916 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
1918 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
1919 state_->GetErrorState());
1920 ScopedTexture2DBinder binder(state_, id_);
1921 glCopyTexImage2D(GL_TEXTURE_2D,
1930 void BackTexture::Destroy() {
1932 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
1933 state_->GetErrorState());
1934 glDeleteTextures(1, &id_);
1937 memory_tracker_.TrackMemFree(bytes_allocated_);
1938 bytes_allocated_ = 0;
1941 void BackTexture::Invalidate() {
1945 BackRenderbuffer::BackRenderbuffer(
1946 RenderbufferManager* renderbuffer_manager,
1947 MemoryTracker* memory_tracker,
1948 ContextState* state)
1949 : renderbuffer_manager_(renderbuffer_manager),
1950 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1952 bytes_allocated_(0),
1956 BackRenderbuffer::~BackRenderbuffer() {
1957 // This does not destroy the render buffer because that would require that
1958 // the associated GL context was current. Just check that it was explicitly
1963 void BackRenderbuffer::Create() {
1964 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
1965 state_->GetErrorState());
1967 glGenRenderbuffersEXT(1, &id_);
1970 bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1972 ScopedGLErrorSuppressor suppressor(
1973 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
1974 ScopedRenderBufferBinder binder(state_, id_);
1976 uint32 estimated_size = 0;
1977 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
1978 size.width(), size.height(), samples, format, &estimated_size)) {
1982 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
1987 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1992 if (GLES2Decoder::IsAngle()) {
1993 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1999 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
2006 bool success = glGetError() == GL_NO_ERROR;
2008 // Mark the previously allocated bytes as free.
2009 memory_tracker_.TrackMemFree(bytes_allocated_);
2010 bytes_allocated_ = estimated_size;
2011 // Track the newly allocated bytes.
2012 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2017 void BackRenderbuffer::Destroy() {
2019 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2020 state_->GetErrorState());
2021 glDeleteRenderbuffersEXT(1, &id_);
2024 memory_tracker_.TrackMemFree(bytes_allocated_);
2025 bytes_allocated_ = 0;
2028 void BackRenderbuffer::Invalidate() {
2032 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2033 : decoder_(decoder),
2037 BackFramebuffer::~BackFramebuffer() {
2038 // This does not destroy the frame buffer because that would require that
2039 // the associated GL context was current. Just check that it was explicitly
2044 void BackFramebuffer::Create() {
2045 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2046 decoder_->GetErrorState());
2048 glGenFramebuffersEXT(1, &id_);
2051 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2053 ScopedGLErrorSuppressor suppressor(
2054 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2055 ScopedFrameBufferBinder binder(decoder_, id_);
2056 GLuint attach_id = texture ? texture->id() : 0;
2057 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2058 GL_COLOR_ATTACHMENT0,
2064 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2065 BackRenderbuffer* render_buffer) {
2067 ScopedGLErrorSuppressor suppressor(
2068 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2069 ScopedFrameBufferBinder binder(decoder_, id_);
2070 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2071 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2077 void BackFramebuffer::Destroy() {
2079 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2080 decoder_->GetErrorState());
2081 glDeleteFramebuffersEXT(1, &id_);
2086 void BackFramebuffer::Invalidate() {
2090 GLenum BackFramebuffer::CheckStatus() {
2092 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2093 decoder_->GetErrorState());
2094 ScopedFrameBufferBinder binder(decoder_, id_);
2095 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2098 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2099 return new GLES2DecoderImpl(group);
2102 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2105 logger_(&debug_marker_manager_),
2106 state_(group_->feature_info(), &logger_),
2107 unpack_flip_y_(false),
2108 unpack_premultiply_alpha_(false),
2109 unpack_unpremultiply_alpha_(false),
2110 attrib_0_buffer_id_(0),
2111 attrib_0_buffer_matches_value_(true),
2113 fixed_attrib_buffer_id_(0),
2114 fixed_attrib_buffer_size_(0),
2115 offscreen_target_color_format_(0),
2116 offscreen_target_depth_format_(0),
2117 offscreen_target_stencil_format_(0),
2118 offscreen_target_samples_(0),
2119 offscreen_target_buffer_preserved_(true),
2120 offscreen_saved_color_format_(0),
2121 back_buffer_color_format_(0),
2122 back_buffer_has_depth_(false),
2123 back_buffer_has_stencil_(false),
2124 backbuffer_needs_clear_bits_(0),
2125 current_decoder_error_(error::kNoError),
2126 use_shader_translator_(true),
2127 validators_(group_->feature_info()->validators()),
2128 feature_info_(group_->feature_info()),
2130 has_robustness_extension_(false),
2131 reset_status_(GL_NO_ERROR),
2132 reset_by_robustness_extension_(false),
2133 force_webgl_glsl_validation_(false),
2134 derivatives_explicitly_enabled_(false),
2135 frag_depth_explicitly_enabled_(false),
2136 draw_buffers_explicitly_enabled_(false),
2137 compile_shader_always_succeeds_(false),
2138 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2139 switches::kEnableGPUServiceLoggingGPU)),
2140 viewport_max_width_(0),
2141 viewport_max_height_(0),
2142 validation_texture_(0),
2143 validation_fbo_multisample_(0),
2144 validation_fbo_(0) {
2147 attrib_0_value_.v[0] = 0.0f;
2148 attrib_0_value_.v[1] = 0.0f;
2149 attrib_0_value_.v[2] = 0.0f;
2150 attrib_0_value_.v[3] = 1.0f;
2152 // The shader translator is used for WebGL even when running on EGL
2153 // because additional restrictions are needed (like only enabling
2154 // GL_OES_standard_derivatives on demand). It is used for the unit
2155 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2156 // the empty string to CompileShader and this is not a valid shader.
2157 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2158 CommandLine::ForCurrentProcess()->HasSwitch(
2159 switches::kDisableGLSLTranslator)) {
2160 use_shader_translator_ = false;
2163 // TODO(gman): Consider setting this based on GPU and/or driver.
2165 texture_state_.teximage2d_faster_than_texsubimage2d = false;
2169 GLES2DecoderImpl::~GLES2DecoderImpl() {
2172 bool GLES2DecoderImpl::Initialize(
2173 const scoped_refptr<gfx::GLSurface>& surface,
2174 const scoped_refptr<gfx::GLContext>& context,
2176 const gfx::Size& size,
2177 const DisallowedFeatures& disallowed_features,
2178 const std::vector<int32>& attribs) {
2179 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2180 DCHECK(context->IsCurrent(surface.get()));
2181 DCHECK(!context_.get());
2184 gpu_tracer_ = GPUTracer::Create();
2185 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2187 if (CommandLine::ForCurrentProcess()->HasSwitch(
2188 switches::kEnableGPUDebugging)) {
2192 if (CommandLine::ForCurrentProcess()->HasSwitch(
2193 switches::kEnableGPUCommandLogging)) {
2194 set_log_commands(true);
2197 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2198 switches::kCompileShaderAlwaysSucceeds);
2201 // Take ownership of the context and surface. The surface can be replaced with
2206 if (!group_->Initialize(this, disallowed_features)) {
2207 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2208 << "failed to initialize.";
2209 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2215 disallowed_features_ = disallowed_features;
2217 state_.attrib_values.resize(group_->max_vertex_attribs());
2218 default_vertex_attrib_manager_ = new VertexAttribManager();
2219 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2221 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2222 DoBindVertexArrayOES(0);
2224 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2225 vertex_array_manager_.reset(new VertexArrayManager());
2227 util_.set_num_compressed_texture_formats(
2228 validators_->compressed_texture_format.GetValues().size());
2230 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2231 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2232 // OpenGL ES 2.0 does not have this issue.
2233 glEnableVertexAttribArray(0);
2235 glGenBuffersARB(1, &attrib_0_buffer_id_);
2236 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2237 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2238 glBindBuffer(GL_ARRAY_BUFFER, 0);
2239 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2241 state_.texture_units.resize(group_->max_texture_units());
2242 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2243 glActiveTexture(GL_TEXTURE0 + tt);
2244 // We want the last bind to be 2D.
2246 if (features().oes_egl_image_external) {
2247 ref = texture_manager()->GetDefaultTextureInfo(
2248 GL_TEXTURE_EXTERNAL_OES);
2249 state_.texture_units[tt].bound_texture_external_oes = ref;
2250 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
2252 if (features().arb_texture_rectangle) {
2253 ref = texture_manager()->GetDefaultTextureInfo(
2254 GL_TEXTURE_RECTANGLE_ARB);
2255 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2256 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
2258 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2259 state_.texture_units[tt].bound_texture_cube_map = ref;
2260 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2261 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2262 state_.texture_units[tt].bound_texture_2d = ref;
2263 glBindTexture(GL_TEXTURE_2D, ref->service_id());
2265 glActiveTexture(GL_TEXTURE0);
2268 ContextCreationAttribHelper attrib_parser;
2269 if (!attrib_parser.Parse(attribs))
2273 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2274 features().chromium_framebuffer_multisample) {
2275 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2276 // max_sample_count must be initialized to a sane value. If
2277 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2278 GLint max_sample_count = 1;
2279 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2280 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2283 offscreen_target_samples_ = 1;
2285 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2287 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2288 const bool rgb8_supported =
2289 context_->HasExtension("GL_OES_rgb8_rgba8");
2290 // The only available default render buffer formats in GLES2 have very
2291 // little precision. Don't enable multisampling unless 8-bit render
2292 // buffer formats are available--instead fall back to 8-bit textures.
2293 if (rgb8_supported && offscreen_target_samples_ > 1) {
2294 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2297 offscreen_target_samples_ = 1;
2298 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2302 // ANGLE only supports packed depth/stencil formats, so use it if it is
2304 const bool depth24_stencil8_supported =
2305 context_->HasExtension("GL_OES_packed_depth_stencil");
2306 VLOG(1) << "GL_OES_packed_depth_stencil "
2307 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2308 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2309 depth24_stencil8_supported) {
2310 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2311 offscreen_target_stencil_format_ = 0;
2313 // It may be the case that this depth/stencil combination is not
2314 // supported, but this will be checked later by CheckFramebufferStatus.
2315 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2316 GL_DEPTH_COMPONENT16 : 0;
2317 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2318 GL_STENCIL_INDEX8 : 0;
2321 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2324 // If depth is requested at all, use the packed depth stencil format if
2325 // it's available, as some desktop GL drivers don't support any non-packed
2326 // formats for depth attachments.
2327 const bool depth24_stencil8_supported =
2328 context_->HasExtension("GL_EXT_packed_depth_stencil");
2329 VLOG(1) << "GL_EXT_packed_depth_stencil "
2330 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2332 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2333 depth24_stencil8_supported) {
2334 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2335 offscreen_target_stencil_format_ = 0;
2337 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2338 GL_DEPTH_COMPONENT : 0;
2339 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2340 GL_STENCIL_INDEX : 0;
2344 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2347 // Create the target frame buffer. This is the one that the client renders
2349 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2350 offscreen_target_frame_buffer_->Create();
2351 // Due to GLES2 format limitations, either the color texture (for
2352 // non-multisampling) or the color render buffer (for multisampling) will be
2353 // attached to the offscreen frame buffer. The render buffer has more
2354 // limited formats available to it, but the texture can't do multisampling.
2355 if (IsOffscreenBufferMultisampled()) {
2356 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2357 renderbuffer_manager(), memory_tracker(), &state_));
2358 offscreen_target_color_render_buffer_->Create();
2360 offscreen_target_color_texture_.reset(new BackTexture(
2361 memory_tracker(), &state_));
2362 offscreen_target_color_texture_->Create();
2364 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2365 renderbuffer_manager(), memory_tracker(), &state_));
2366 offscreen_target_depth_render_buffer_->Create();
2367 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2368 renderbuffer_manager(), memory_tracker(), &state_));
2369 offscreen_target_stencil_render_buffer_->Create();
2371 // Create the saved offscreen texture. The target frame buffer is copied
2372 // here when SwapBuffers is called.
2373 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2374 offscreen_saved_frame_buffer_->Create();
2376 offscreen_saved_color_texture_.reset(new BackTexture(
2377 memory_tracker(), &state_));
2378 offscreen_saved_color_texture_->Create();
2380 // Allocate the render buffers at their initial size and check the status
2381 // of the frame buffers is okay.
2382 if (!ResizeOffscreenFrameBuffer(size)) {
2383 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2388 // Allocate the offscreen saved color texture.
2389 DCHECK(offscreen_saved_color_format_);
2390 offscreen_saved_color_texture_->AllocateStorage(
2391 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2393 offscreen_saved_frame_buffer_->AttachRenderTexture(
2394 offscreen_saved_color_texture_.get());
2395 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2396 GL_FRAMEBUFFER_COMPLETE) {
2397 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2402 // Bind to the new default frame buffer (the offscreen target frame buffer).
2403 // This should now be associated with ID zero.
2404 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2406 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2407 // These are NOT if the back buffer has these proprorties. They are
2408 // if we want the command buffer to enforce them regardless of what
2409 // the real backbuffer is assuming the real back buffer gives us more than
2410 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2411 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2412 // can't do anything about that.
2415 glGetIntegerv(GL_ALPHA_BITS, &v);
2416 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2417 // user requested RGB then RGB. If the user did not specify a preference
2418 // than use whatever we were given. Same for DEPTH and STENCIL.
2419 back_buffer_color_format_ =
2420 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2421 glGetIntegerv(GL_DEPTH_BITS, &v);
2422 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2423 glGetIntegerv(GL_STENCIL_BITS, &v);
2424 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2427 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2428 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2429 // isn't well documented; it was discovered in the Khronos OpenGL ES
2430 // mailing list archives. It also implicitly enables the desktop GL
2431 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2432 // variable in fragment shaders.
2433 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2434 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2435 glEnable(GL_POINT_SPRITE);
2438 has_robustness_extension_ =
2439 context->HasExtension("GL_ARB_robustness") ||
2440 context->HasExtension("GL_EXT_robustness");
2442 if (!InitializeShaderTranslator()) {
2446 state_.viewport_width = size.width();
2447 state_.viewport_height = size.height();
2449 GLint viewport_params[4] = { 0 };
2450 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2451 viewport_max_width_ = viewport_params[0];
2452 viewport_max_height_ = viewport_params[1];
2454 state_.scissor_width = state_.viewport_width;
2455 state_.scissor_height = state_.viewport_height;
2457 // Set all the default state because some GL drivers get it wrong.
2458 state_.InitCapabilities();
2460 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2462 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2463 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2464 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2465 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2467 bool call_gl_clear = true;
2468 #if defined(OS_ANDROID)
2469 // Temporary workaround for Android WebView because this clear ignores the
2470 // clip and corrupts that external UI of the App. Not calling glClear is ok
2471 // because the system already clears the buffer before each draw. Proper
2472 // fix might be setting the scissor clip properly before initialize. See
2473 // crbug.com/259023 for details.
2474 call_gl_clear = surface_->GetHandle();
2476 if (call_gl_clear) {
2477 // Clear the backbuffer.
2478 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2481 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2482 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2485 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2486 context_->SetUnbindFboOnMakeCurrent();
2489 // Only compositor contexts are known to use only the subset of GL
2490 // that can be safely migrated between the iGPU and the dGPU. Mark
2491 // those contexts as safe to forcibly transition between the GPUs.
2492 // http://crbug.com/180876, http://crbug.com/227228
2494 context_->SetSafeToForceGpuSwitch();
2496 async_pixel_transfer_manager_.reset(
2497 AsyncPixelTransferManager::Create(context.get()));
2498 async_pixel_transfer_manager_->Initialize(texture_manager());
2500 framebuffer_manager()->AddObserver(this);
2505 void GLES2DecoderImpl::UpdateCapabilities() {
2506 util_.set_num_compressed_texture_formats(
2507 validators_->compressed_texture_format.GetValues().size());
2508 util_.set_num_shader_binary_formats(
2509 validators_->shader_binary_format.GetValues().size());
2512 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2513 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2515 if (!use_shader_translator_) {
2518 ShBuiltInResources resources;
2519 ShInitBuiltInResources(&resources);
2520 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2521 resources.MaxVertexUniformVectors =
2522 group_->max_vertex_uniform_vectors();
2523 resources.MaxVaryingVectors = group_->max_varying_vectors();
2524 resources.MaxVertexTextureImageUnits =
2525 group_->max_vertex_texture_image_units();
2526 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2527 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2528 resources.MaxFragmentUniformVectors =
2529 group_->max_fragment_uniform_vectors();
2530 resources.MaxDrawBuffers = group_->max_draw_buffers();
2531 resources.MaxExpressionComplexity = 256;
2532 resources.MaxCallStackDepth = 256;
2534 #if (ANGLE_SH_VERSION >= 110)
2535 GLint range[2] = { 0, 0 };
2536 GLint precision = 0;
2537 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2539 resources.FragmentPrecisionHigh =
2540 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2543 if (force_webgl_glsl_validation_) {
2544 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2545 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2546 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2547 if (!draw_buffers_explicitly_enabled_)
2548 resources.MaxDrawBuffers = 1;
2550 resources.OES_standard_derivatives =
2551 features().oes_standard_derivatives ? 1 : 0;
2552 resources.ARB_texture_rectangle =
2553 features().arb_texture_rectangle ? 1 : 0;
2554 resources.OES_EGL_image_external =
2555 features().oes_egl_image_external ? 1 : 0;
2556 resources.EXT_draw_buffers =
2557 features().ext_draw_buffers ? 1 : 0;
2558 resources.EXT_frag_depth =
2559 features().ext_frag_depth ? 1 : 0;
2562 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2564 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2565 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2566 resources.HashFunction = &CityHashForAngle;
2568 resources.HashFunction = &CityHash64;
2571 resources.HashFunction = NULL;
2572 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2573 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2574 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2575 int driver_bug_workarounds = 0;
2576 if (workarounds().needs_glsl_built_in_function_emulation)
2577 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2578 if (workarounds().init_gl_position_in_vertex_shader)
2579 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2580 if (workarounds().unfold_short_circuit_as_ternary_operation)
2581 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2583 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2584 vertex_translator_ = cache->GetTranslator(
2585 SH_VERTEX_SHADER, shader_spec, &resources,
2586 implementation_type,
2587 static_cast<ShCompileOptions>(driver_bug_workarounds));
2588 if (!vertex_translator_.get()) {
2589 LOG(ERROR) << "Could not initialize vertex shader translator.";
2594 fragment_translator_ = cache->GetTranslator(
2595 SH_FRAGMENT_SHADER, shader_spec, &resources,
2596 implementation_type,
2597 static_cast<ShCompileOptions>(driver_bug_workarounds));
2598 if (!fragment_translator_.get()) {
2599 LOG(ERROR) << "Could not initialize fragment shader translator.";
2606 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2607 for (GLsizei ii = 0; ii < n; ++ii) {
2608 if (GetBuffer(client_ids[ii])) {
2612 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2613 glGenBuffersARB(n, service_ids.get());
2614 for (GLsizei ii = 0; ii < n; ++ii) {
2615 CreateBuffer(client_ids[ii], service_ids[ii]);
2620 bool GLES2DecoderImpl::GenFramebuffersHelper(
2621 GLsizei n, const GLuint* client_ids) {
2622 for (GLsizei ii = 0; ii < n; ++ii) {
2623 if (GetFramebuffer(client_ids[ii])) {
2627 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2628 glGenFramebuffersEXT(n, service_ids.get());
2629 for (GLsizei ii = 0; ii < n; ++ii) {
2630 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2635 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2636 GLsizei n, const GLuint* client_ids) {
2637 for (GLsizei ii = 0; ii < n; ++ii) {
2638 if (GetRenderbuffer(client_ids[ii])) {
2642 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2643 glGenRenderbuffersEXT(n, service_ids.get());
2644 for (GLsizei ii = 0; ii < n; ++ii) {
2645 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2650 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2651 for (GLsizei ii = 0; ii < n; ++ii) {
2652 if (GetTexture(client_ids[ii])) {
2656 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2657 glGenTextures(n, service_ids.get());
2658 for (GLsizei ii = 0; ii < n; ++ii) {
2659 CreateTexture(client_ids[ii], service_ids[ii]);
2664 void GLES2DecoderImpl::DeleteBuffersHelper(
2665 GLsizei n, const GLuint* client_ids) {
2666 for (GLsizei ii = 0; ii < n; ++ii) {
2667 Buffer* buffer = GetBuffer(client_ids[ii]);
2668 if (buffer && !buffer->IsDeleted()) {
2669 state_.vertex_attrib_manager->Unbind(buffer);
2670 if (state_.bound_array_buffer.get() == buffer) {
2671 state_.bound_array_buffer = NULL;
2673 RemoveBuffer(client_ids[ii]);
2678 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2679 GLsizei n, const GLuint* client_ids) {
2680 bool supports_separate_framebuffer_binds =
2681 features().chromium_framebuffer_multisample;
2683 for (GLsizei ii = 0; ii < n; ++ii) {
2684 Framebuffer* framebuffer =
2685 GetFramebuffer(client_ids[ii]);
2686 if (framebuffer && !framebuffer->IsDeleted()) {
2687 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2688 framebuffer_state_.bound_draw_framebuffer = NULL;
2689 framebuffer_state_.clear_state_dirty = true;
2690 GLenum target = supports_separate_framebuffer_binds ?
2691 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2692 glBindFramebufferEXT(target, GetBackbufferServiceId());
2694 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2695 framebuffer_state_.bound_read_framebuffer = NULL;
2696 GLenum target = supports_separate_framebuffer_binds ?
2697 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2698 glBindFramebufferEXT(target, GetBackbufferServiceId());
2701 RemoveFramebuffer(client_ids[ii]);
2706 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2707 GLsizei n, const GLuint* client_ids) {
2708 bool supports_separate_framebuffer_binds =
2709 features().chromium_framebuffer_multisample;
2710 for (GLsizei ii = 0; ii < n; ++ii) {
2711 Renderbuffer* renderbuffer =
2712 GetRenderbuffer(client_ids[ii]);
2713 if (renderbuffer && !renderbuffer->IsDeleted()) {
2714 if (state_.bound_renderbuffer.get() == renderbuffer) {
2715 state_.bound_renderbuffer = NULL;
2717 // Unbind from current framebuffers.
2718 if (supports_separate_framebuffer_binds) {
2719 if (framebuffer_state_.bound_read_framebuffer.get()) {
2720 framebuffer_state_.bound_read_framebuffer
2721 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2723 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2724 framebuffer_state_.bound_draw_framebuffer
2725 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2728 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2729 framebuffer_state_.bound_draw_framebuffer
2730 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2733 framebuffer_state_.clear_state_dirty = true;
2734 RemoveRenderbuffer(client_ids[ii]);
2739 void GLES2DecoderImpl::DeleteTexturesHelper(
2740 GLsizei n, const GLuint* client_ids) {
2741 bool supports_separate_framebuffer_binds =
2742 features().chromium_framebuffer_multisample;
2743 for (GLsizei ii = 0; ii < n; ++ii) {
2744 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2746 Texture* texture = texture_ref->texture();
2747 if (texture->IsAttachedToFramebuffer()) {
2748 framebuffer_state_.clear_state_dirty = true;
2750 // Unbind texture_ref from texture_ref units.
2751 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2752 state_.texture_units[jj].Unbind(texture_ref);
2754 // Unbind from current framebuffers.
2755 if (supports_separate_framebuffer_binds) {
2756 if (framebuffer_state_.bound_read_framebuffer.get()) {
2757 framebuffer_state_.bound_read_framebuffer
2758 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2760 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2761 framebuffer_state_.bound_draw_framebuffer
2762 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2765 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2766 framebuffer_state_.bound_draw_framebuffer
2767 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2770 #if defined(OS_MACOSX)
2771 GLuint service_id = texture->service_id();
2772 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2773 ReleaseIOSurfaceForTexture(service_id);
2776 RemoveTexture(client_ids[ii]);
2781 // } // anonymous namespace
2783 bool GLES2DecoderImpl::MakeCurrent() {
2784 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2787 if (WasContextLost()) {
2788 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2790 // Some D3D drivers cannot recover from device lost in the GPU process
2791 // sandbox. Allow a new GPU process to launch.
2792 if (workarounds().exit_on_context_lost) {
2793 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2794 << " a D3D device in the Chrome GPU process sandbox.";
2796 base::win::SetShouldCrashOnProcessDetach(false);
2804 ProcessFinishedAsyncTransfers();
2806 // Rebind the FBO if it was unbound by the context.
2807 if (workarounds().unbind_fbo_on_context_switch)
2808 RestoreFramebufferBindings();
2810 framebuffer_state_.clear_state_dirty = true;
2815 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
2816 ProcessPendingReadPixels();
2817 if (engine() && query_manager_.get())
2818 query_manager_->ProcessPendingTransferQueries();
2820 // TODO(epenner): Is there a better place to do this?
2821 // This needs to occur before we execute any batch of commands
2822 // from the client, as the client may have recieved an async
2823 // completion while issuing those commands.
2824 // "DidFlushStart" would be ideal if we had such a callback.
2825 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
2828 void GLES2DecoderImpl::ReleaseCurrent() {
2830 context_->ReleaseCurrent(surface_.get());
2833 static void RebindCurrentFramebuffer(
2835 Framebuffer* framebuffer,
2836 GLuint back_buffer_service_id) {
2837 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
2839 if (framebuffer_id == 0) {
2840 framebuffer_id = back_buffer_service_id;
2843 glBindFramebufferEXT(target, framebuffer_id);
2846 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
2847 framebuffer_state_.clear_state_dirty = true;
2849 if (!features().chromium_framebuffer_multisample) {
2850 RebindCurrentFramebuffer(
2852 framebuffer_state_.bound_draw_framebuffer.get(),
2853 GetBackbufferServiceId());
2855 RebindCurrentFramebuffer(
2856 GL_READ_FRAMEBUFFER_EXT,
2857 framebuffer_state_.bound_read_framebuffer.get(),
2858 GetBackbufferServiceId());
2859 RebindCurrentFramebuffer(
2860 GL_DRAW_FRAMEBUFFER_EXT,
2861 framebuffer_state_.bound_draw_framebuffer.get(),
2862 GetBackbufferServiceId());
2867 bool GLES2DecoderImpl::CheckFramebufferValid(
2868 Framebuffer* framebuffer,
2869 GLenum target, const char* func_name) {
2871 if (backbuffer_needs_clear_bits_) {
2872 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2873 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2874 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2879 glDisable(GL_SCISSOR_TEST);
2880 glClear(backbuffer_needs_clear_bits_);
2881 backbuffer_needs_clear_bits_ = 0;
2882 RestoreClearState();
2887 if (framebuffer_manager()->IsComplete(framebuffer)) {
2891 GLenum completeness = framebuffer->IsPossiblyComplete();
2892 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2894 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
2898 // Are all the attachments cleared?
2899 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2900 texture_manager()->HaveUnclearedMips()) {
2901 if (!framebuffer->IsCleared()) {
2902 // Can we clear them?
2903 if (framebuffer->GetStatus(texture_manager(), target) !=
2904 GL_FRAMEBUFFER_COMPLETE) {
2906 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2907 "framebuffer incomplete (clear)");
2910 ClearUnclearedAttachments(target, framebuffer);
2914 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2915 if (framebuffer->GetStatus(texture_manager(), target) !=
2916 GL_FRAMEBUFFER_COMPLETE) {
2918 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2919 "framebuffer incomplete (check)");
2922 framebuffer_manager()->MarkAsComplete(framebuffer);
2925 // NOTE: At this point we don't know if the framebuffer is complete but
2926 // we DO know that everything that needs to be cleared has been cleared.
2930 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2931 if (!features().chromium_framebuffer_multisample) {
2932 bool valid = CheckFramebufferValid(
2933 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
2941 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
2942 GL_DRAW_FRAMEBUFFER_EXT,
2944 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
2945 GL_READ_FRAMEBUFFER_EXT,
2949 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2950 Framebuffer* framebuffer =
2951 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
2952 if (framebuffer != NULL) {
2953 const Framebuffer::Attachment* attachment =
2954 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
2956 return gfx::Size(attachment->width(), attachment->height());
2958 return gfx::Size(0, 0);
2959 } else if (offscreen_target_frame_buffer_.get()) {
2960 return offscreen_size_;
2962 return surface_->GetSize();
2966 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2967 Framebuffer* framebuffer =
2968 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
2969 if (framebuffer != NULL) {
2970 return framebuffer->GetColorAttachmentFormat();
2971 } else if (offscreen_target_frame_buffer_.get()) {
2972 return offscreen_target_color_format_;
2974 return back_buffer_color_format_;
2978 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
2979 Framebuffer* framebuffer =
2980 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
2981 if (framebuffer != NULL) {
2982 return framebuffer->GetColorAttachmentFormat();
2983 } else if (offscreen_target_frame_buffer_.get()) {
2984 return offscreen_target_color_format_;
2986 return back_buffer_color_format_;
2990 void GLES2DecoderImpl::UpdateParentTextureInfo() {
2991 if (!offscreen_saved_color_texture_info_.get())
2993 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
2994 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
2995 texture_manager()->SetLevelInfo(
2996 offscreen_saved_color_texture_info_.get(),
3000 offscreen_size_.width(),
3001 offscreen_size_.height(),
3007 texture_manager()->SetParameter(
3008 "UpdateParentTextureInfo",
3010 offscreen_saved_color_texture_info_.get(),
3011 GL_TEXTURE_MAG_FILTER,
3013 texture_manager()->SetParameter(
3014 "UpdateParentTextureInfo",
3016 offscreen_saved_color_texture_info_.get(),
3017 GL_TEXTURE_MIN_FILTER,
3019 texture_manager()->SetParameter(
3020 "UpdateParentTextureInfo",
3022 offscreen_saved_color_texture_info_.get(),
3025 texture_manager()->SetParameter(
3026 "UpdateParentTextureInfo",
3028 offscreen_saved_color_texture_info_.get(),
3031 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3033 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3036 void GLES2DecoderImpl::SetResizeCallback(
3037 const base::Callback<void(gfx::Size, float)>& callback) {
3038 resize_callback_ = callback;
3041 Logger* GLES2DecoderImpl::GetLogger() {
3045 ErrorState* GLES2DecoderImpl::GetErrorState() {
3046 return state_.GetErrorState();
3049 void GLES2DecoderImpl::SetShaderCacheCallback(
3050 const ShaderCacheCallback& callback) {
3051 shader_cache_callback_ = callback;
3054 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3055 const WaitSyncPointCallback& callback) {
3056 wait_sync_point_callback_ = callback;
3059 AsyncPixelTransferManager*
3060 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3061 return async_pixel_transfer_manager_.get();
3064 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3065 async_pixel_transfer_manager_.reset();
3068 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3069 AsyncPixelTransferManager* manager) {
3070 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3073 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3074 uint32* service_texture_id) {
3075 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3077 *service_texture_id = texture_ref->service_id();
3083 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3084 return texture_state_.texture_upload_count +
3085 async_pixel_transfer_manager_->GetTextureUploadCount();
3088 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3089 return texture_state_.total_texture_upload_time +
3090 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3093 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3094 return total_processing_commands_time_;
3097 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3098 total_processing_commands_time_ += time;
3101 void GLES2DecoderImpl::Destroy(bool have_context) {
3105 DCHECK(!have_context || context_->IsCurrent(NULL));
3107 // Unbind everything.
3108 state_.vertex_attrib_manager = NULL;
3109 default_vertex_attrib_manager_ = NULL;
3110 state_.texture_units.clear();
3111 state_.bound_array_buffer = NULL;
3112 state_.current_query = NULL;
3113 framebuffer_state_.bound_read_framebuffer = NULL;
3114 framebuffer_state_.bound_draw_framebuffer = NULL;
3115 state_.bound_renderbuffer = NULL;
3117 if (offscreen_saved_color_texture_info_.get()) {
3118 DCHECK(offscreen_target_color_texture_);
3119 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3120 offscreen_saved_color_texture_->id());
3121 offscreen_saved_color_texture_->Invalidate();
3122 offscreen_saved_color_texture_info_ = NULL;
3125 if (copy_texture_CHROMIUM_.get()) {
3126 copy_texture_CHROMIUM_->Destroy();
3127 copy_texture_CHROMIUM_.reset();
3130 if (state_.current_program.get()) {
3131 program_manager()->UnuseProgram(shader_manager(),
3132 state_.current_program.get());
3135 if (attrib_0_buffer_id_) {
3136 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3138 if (fixed_attrib_buffer_id_) {
3139 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3142 if (validation_texture_) {
3143 glDeleteTextures(1, &validation_texture_);
3144 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3145 glDeleteFramebuffersEXT(1, &validation_fbo_);
3148 if (offscreen_target_frame_buffer_.get())
3149 offscreen_target_frame_buffer_->Destroy();
3150 if (offscreen_target_color_texture_.get())
3151 offscreen_target_color_texture_->Destroy();
3152 if (offscreen_target_color_render_buffer_.get())
3153 offscreen_target_color_render_buffer_->Destroy();
3154 if (offscreen_target_depth_render_buffer_.get())
3155 offscreen_target_depth_render_buffer_->Destroy();
3156 if (offscreen_target_stencil_render_buffer_.get())
3157 offscreen_target_stencil_render_buffer_->Destroy();
3158 if (offscreen_saved_frame_buffer_.get())
3159 offscreen_saved_frame_buffer_->Destroy();
3160 if (offscreen_saved_color_texture_.get())
3161 offscreen_saved_color_texture_->Destroy();
3162 if (offscreen_resolved_frame_buffer_.get())
3163 offscreen_resolved_frame_buffer_->Destroy();
3164 if (offscreen_resolved_color_texture_.get())
3165 offscreen_resolved_color_texture_->Destroy();
3167 if (offscreen_target_frame_buffer_.get())
3168 offscreen_target_frame_buffer_->Invalidate();
3169 if (offscreen_target_color_texture_.get())
3170 offscreen_target_color_texture_->Invalidate();
3171 if (offscreen_target_color_render_buffer_.get())
3172 offscreen_target_color_render_buffer_->Invalidate();
3173 if (offscreen_target_depth_render_buffer_.get())
3174 offscreen_target_depth_render_buffer_->Invalidate();
3175 if (offscreen_target_stencil_render_buffer_.get())
3176 offscreen_target_stencil_render_buffer_->Invalidate();
3177 if (offscreen_saved_frame_buffer_.get())
3178 offscreen_saved_frame_buffer_->Invalidate();
3179 if (offscreen_saved_color_texture_.get())
3180 offscreen_saved_color_texture_->Invalidate();
3181 if (offscreen_resolved_frame_buffer_.get())
3182 offscreen_resolved_frame_buffer_->Invalidate();
3183 if (offscreen_resolved_color_texture_.get())
3184 offscreen_resolved_color_texture_->Invalidate();
3187 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3188 // Otherwise, we can leak objects. http://crbug.com/258772.
3189 // state_.current_program must be reset before group_ is reset because
3190 // the later deletes the ProgramManager object that referred by
3191 // state_.current_program object.
3192 state_.current_program = NULL;
3194 copy_texture_CHROMIUM_.reset();
3196 if (query_manager_.get()) {
3197 query_manager_->Destroy(have_context);
3198 query_manager_.reset();
3201 if (vertex_array_manager_ .get()) {
3202 vertex_array_manager_->Destroy(have_context);
3203 vertex_array_manager_.reset();
3206 offscreen_target_frame_buffer_.reset();
3207 offscreen_target_color_texture_.reset();
3208 offscreen_target_color_render_buffer_.reset();
3209 offscreen_target_depth_render_buffer_.reset();
3210 offscreen_target_stencil_render_buffer_.reset();
3211 offscreen_saved_frame_buffer_.reset();
3212 offscreen_saved_color_texture_.reset();
3213 offscreen_resolved_frame_buffer_.reset();
3214 offscreen_resolved_color_texture_.reset();
3216 // Should destroy the transfer manager before the texture manager held
3217 // by the context group.
3218 async_pixel_transfer_manager_.reset();
3220 framebuffer_manager()->RemoveObserver(this);
3223 group_->Destroy(this, have_context);
3227 if (context_.get()) {
3228 context_->ReleaseCurrent(NULL);
3232 #if defined(OS_MACOSX)
3233 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3234 it != texture_to_io_surface_map_.end(); ++it) {
3235 CFRelease(it->second);
3237 texture_to_io_surface_map_.clear();
3241 void GLES2DecoderImpl::SetSurface(
3242 const scoped_refptr<gfx::GLSurface>& surface) {
3243 DCHECK(context_->IsCurrent(NULL));
3244 DCHECK(surface_.get());
3246 RestoreCurrentFramebufferBindings();
3249 bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3250 if (!offscreen_saved_color_texture_.get())
3252 if (!offscreen_saved_color_texture_info_.get()) {
3253 GLuint service_id = offscreen_saved_color_texture_->id();
3254 offscreen_saved_color_texture_info_ = TextureRef::Create(
3255 texture_manager(), 0, service_id);
3256 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3258 UpdateParentTextureInfo();
3260 gpu::gles2::MailboxName name;
3261 memcpy(name.key, mailbox.name, sizeof(mailbox.name));
3262 return mailbox_manager()->ProduceTexture(
3263 GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
3266 size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
3268 if (offscreen_target_frame_buffer_.get()) {
3269 if (offscreen_target_color_texture_.get()) {
3270 total += offscreen_target_color_texture_->estimated_size();
3272 if (offscreen_target_color_render_buffer_.get()) {
3273 total += offscreen_target_color_render_buffer_->estimated_size();
3275 if (offscreen_target_depth_render_buffer_.get()) {
3276 total += offscreen_target_depth_render_buffer_->estimated_size();
3278 if (offscreen_target_stencil_render_buffer_.get()) {
3279 total += offscreen_target_stencil_render_buffer_->estimated_size();
3281 if (offscreen_saved_color_texture_.get()) {
3282 total += offscreen_saved_color_texture_->estimated_size();
3284 if (offscreen_resolved_color_texture_.get()) {
3285 total += offscreen_resolved_color_texture_->estimated_size();
3288 gfx::Size size = surface_->GetSize();
3289 total += size.width() * size.height() *
3290 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3295 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3296 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3297 if (!is_offscreen) {
3298 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3299 << " with an onscreen framebuffer.";
3303 if (offscreen_size_ == size)
3306 offscreen_size_ = size;
3307 int w = offscreen_size_.width();
3308 int h = offscreen_size_.height();
3309 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3310 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3311 << "to allocate storage due to excessive dimensions.";
3315 // Reallocate the offscreen target buffers.
3316 DCHECK(offscreen_target_color_format_);
3317 if (IsOffscreenBufferMultisampled()) {
3318 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3319 offscreen_size_, offscreen_target_color_format_,
3320 offscreen_target_samples_)) {
3321 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3322 << "to allocate storage for offscreen target color buffer.";
3326 if (!offscreen_target_color_texture_->AllocateStorage(
3327 offscreen_size_, offscreen_target_color_format_, false)) {
3328 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3329 << "to allocate storage for offscreen target color texture.";
3333 if (offscreen_target_depth_format_ &&
3334 !offscreen_target_depth_render_buffer_->AllocateStorage(
3335 offscreen_size_, offscreen_target_depth_format_,
3336 offscreen_target_samples_)) {
3337 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3338 << "to allocate storage for offscreen target depth buffer.";
3341 if (offscreen_target_stencil_format_ &&
3342 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3343 offscreen_size_, offscreen_target_stencil_format_,
3344 offscreen_target_samples_)) {
3345 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3346 << "to allocate storage for offscreen target stencil buffer.";
3350 // Attach the offscreen target buffers to the target frame buffer.
3351 if (IsOffscreenBufferMultisampled()) {
3352 offscreen_target_frame_buffer_->AttachRenderBuffer(
3353 GL_COLOR_ATTACHMENT0,
3354 offscreen_target_color_render_buffer_.get());
3356 offscreen_target_frame_buffer_->AttachRenderTexture(
3357 offscreen_target_color_texture_.get());
3359 if (offscreen_target_depth_format_) {
3360 offscreen_target_frame_buffer_->AttachRenderBuffer(
3361 GL_DEPTH_ATTACHMENT,
3362 offscreen_target_depth_render_buffer_.get());
3364 const bool packed_depth_stencil =
3365 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3366 if (packed_depth_stencil) {
3367 offscreen_target_frame_buffer_->AttachRenderBuffer(
3368 GL_STENCIL_ATTACHMENT,
3369 offscreen_target_depth_render_buffer_.get());
3370 } else if (offscreen_target_stencil_format_) {
3371 offscreen_target_frame_buffer_->AttachRenderBuffer(
3372 GL_STENCIL_ATTACHMENT,
3373 offscreen_target_stencil_render_buffer_.get());
3376 if (offscreen_target_frame_buffer_->CheckStatus() !=
3377 GL_FRAMEBUFFER_COMPLETE) {
3378 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3379 << "because offscreen FBO was incomplete.";
3383 // Clear the target frame buffer.
3385 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3386 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3387 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3388 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3390 glStencilMaskSeparate(GL_FRONT, -1);
3391 glStencilMaskSeparate(GL_BACK, -1);
3393 glDepthMask(GL_TRUE);
3394 glDisable(GL_SCISSOR_TEST);
3395 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3396 RestoreClearState();
3399 // Destroy the offscreen resolved framebuffers.
3400 if (offscreen_resolved_frame_buffer_.get())
3401 offscreen_resolved_frame_buffer_->Destroy();
3402 if (offscreen_resolved_color_texture_.get())
3403 offscreen_resolved_color_texture_->Destroy();
3404 offscreen_resolved_color_texture_.reset();
3405 offscreen_resolved_frame_buffer_.reset();
3410 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3411 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3412 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3413 return error::kDeferCommandUntilLater;
3415 GLuint width = static_cast<GLuint>(c.width);
3416 GLuint height = static_cast<GLuint>(c.height);
3417 GLfloat scale_factor = c.scale_factor;
3418 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3420 width = std::max(1U, width);
3421 height = std::max(1U, height);
3423 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3424 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3425 // Make sure that we are done drawing to the back buffer before resizing.
3428 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3430 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3431 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3432 << "ResizeOffscreenFrameBuffer failed.";
3433 return error::kLostContext;
3437 if (!resize_callback_.is_null()) {
3438 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3439 DCHECK(context_->IsCurrent(surface_.get()));
3440 if (!context_->IsCurrent(surface_.get())) {
3441 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3442 << "current after resize callback.";
3443 return error::kLostContext;
3447 return error::kNoError;
3450 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3451 if (command_id > kStartPoint && command_id < kNumCommands) {
3452 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3454 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3457 // Decode command with its arguments, and call the corresponding GL function.
3458 // Note: args is a pointer to the command buffer. As such, it could be changed
3459 // by a (malicious) client at any time, so if validation has to happen, it
3460 // should operate on a copy of them.
3461 error::Error GLES2DecoderImpl::DoCommand(
3462 unsigned int command,
3463 unsigned int arg_count,
3464 const void* cmd_data) {
3465 error::Error result = error::kNoError;
3466 if (log_commands()) {
3467 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3468 // LOG(INFO), tried VLOG(1), no luck.
3469 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3470 << GetCommandName(command);
3472 unsigned int command_index = command - kStartPoint - 1;
3473 if (command_index < arraysize(g_command_info)) {
3474 const CommandInfo& info = g_command_info[command_index];
3475 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3476 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3477 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3478 uint32 immediate_data_size =
3479 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3481 #define GLES2_CMD_OP(name) \
3482 case cmds::name::kCmdId: \
3483 result = Handle ## name( \
3484 immediate_data_size, \
3485 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3488 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3493 while ((error = glGetError()) != GL_NO_ERROR) {
3494 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3495 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3496 << GetCommandName(command);
3497 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3501 result = error::kInvalidArguments;
3504 result = DoCommonCommand(command, arg_count, cmd_data);
3506 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3507 result = current_decoder_error_;
3508 current_decoder_error_ = error::kNoError;
3513 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3514 buffer_manager()->RemoveBuffer(client_id);
3517 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3518 if (GetProgram(client_id)) {
3521 GLuint service_id = glCreateProgram();
3522 if (service_id != 0) {
3523 CreateProgram(client_id, service_id);
3528 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3529 if (GetShader(client_id)) {
3532 GLuint service_id = glCreateShader(type);
3533 if (service_id != 0) {
3534 CreateShader(client_id, service_id, type);
3539 void GLES2DecoderImpl::DoFinish() {
3541 ProcessPendingReadPixels();
3542 ProcessPendingQueries();
3545 void GLES2DecoderImpl::DoFlush() {
3547 ProcessPendingQueries();
3550 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3551 GLuint texture_index = texture_unit - GL_TEXTURE0;
3552 if (texture_index >= state_.texture_units.size()) {
3553 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3554 "glActiveTexture", texture_unit, "texture_unit");
3557 state_.active_texture_unit = texture_index;
3558 glActiveTexture(texture_unit);
3561 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3562 Buffer* buffer = NULL;
3563 GLuint service_id = 0;
3564 if (client_id != 0) {
3565 buffer = GetBuffer(client_id);
3567 if (!group_->bind_generates_resource()) {
3568 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3569 current_decoder_error_ = error::kGenericError;
3573 // It's a new id so make a buffer buffer for it.
3574 glGenBuffersARB(1, &service_id);
3575 CreateBuffer(client_id, service_id);
3576 buffer = GetBuffer(client_id);
3577 IdAllocatorInterface* id_allocator =
3578 group_->GetIdAllocator(id_namespaces::kBuffers);
3579 id_allocator->MarkAsUsed(client_id);
3582 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3584 if (!buffer_manager()->SetTarget(buffer, target)) {
3586 GL_INVALID_OPERATION,
3587 "glBindBuffer", "buffer bound to more than 1 target");
3590 service_id = buffer->service_id();
3593 case GL_ARRAY_BUFFER:
3594 state_.bound_array_buffer = buffer;
3596 case GL_ELEMENT_ARRAY_BUFFER:
3597 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3600 NOTREACHED(); // Validation should prevent us getting here.
3603 glBindBuffer(target, service_id);
3606 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3607 bool all_draw_buffers) {
3608 Framebuffer* framebuffer =
3609 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3610 if (!all_draw_buffers || !framebuffer) {
3611 return (GLES2Util::GetChannelsForFormat(
3612 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3614 return framebuffer->HasAlphaMRT();
3617 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3618 Framebuffer* framebuffer =
3619 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3621 return framebuffer->HasDepthAttachment();
3623 if (offscreen_target_frame_buffer_.get()) {
3624 return offscreen_target_depth_format_ != 0;
3626 return back_buffer_has_depth_;
3629 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3630 Framebuffer* framebuffer =
3631 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3633 return framebuffer->HasStencilAttachment();
3635 if (offscreen_target_frame_buffer_.get()) {
3636 return offscreen_target_stencil_format_ != 0 ||
3637 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3639 return back_buffer_has_stencil_;
3642 void GLES2DecoderImpl::ApplyDirtyState() {
3643 if (framebuffer_state_.clear_state_dirty) {
3645 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3646 state_.color_mask_alpha &&
3647 BoundFramebufferHasColorAttachmentWithAlpha(true));
3648 bool have_depth = BoundFramebufferHasDepthAttachment();
3649 glDepthMask(state_.depth_mask && have_depth);
3650 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3651 bool have_stencil = BoundFramebufferHasStencilAttachment();
3652 glStencilMaskSeparate(
3653 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3654 glStencilMaskSeparate(
3655 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3657 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3658 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3659 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3660 EnableDisable(GL_BLEND, state_.enable_flags.blend);
3661 framebuffer_state_.clear_state_dirty = false;
3665 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3666 return (offscreen_target_frame_buffer_.get())
3667 ? offscreen_target_frame_buffer_->id()
3668 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3671 void GLES2DecoderImpl::RestoreState() const {
3672 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3673 "context", logger_.GetLogPrefix());
3674 // Restore the Framebuffer first because of bugs in Intel drivers.
3675 // Intel drivers incorrectly clip the viewport settings to
3676 // the size of the current framebuffer object.
3677 RestoreFramebufferBindings();
3678 state_.RestoreState();
3681 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3683 framebuffer_state_.bound_draw_framebuffer.get()
3684 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3685 : GetBackbufferServiceId();
3686 if (!features().chromium_framebuffer_multisample) {
3687 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3689 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3690 service_id = framebuffer_state_.bound_read_framebuffer.get()
3691 ? framebuffer_state_.bound_read_framebuffer->service_id()
3692 : GetBackbufferServiceId();
3693 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3698 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3699 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3701 GLenum target = texture->target();
3702 glBindTexture(target, service_id);
3704 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3706 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3708 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3710 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3711 RestoreTextureUnitBindings(state_.active_texture_unit);
3715 void GLES2DecoderImpl::OnFboChanged() const {
3716 if (workarounds().restore_scissor_on_fbo_change)
3717 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3720 // Called after the FBO is checked for completeness.
3721 void GLES2DecoderImpl::OnUseFramebuffer() const {
3722 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3723 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3724 // The driver forgets the correct scissor when modifying the FBO binding.
3725 glScissor(state_.scissor_x,
3727 state_.scissor_width,
3728 state_.scissor_height);
3730 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3731 // it's unclear how this bug works.
3736 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3737 Framebuffer* framebuffer = NULL;
3738 GLuint service_id = 0;
3739 if (client_id != 0) {
3740 framebuffer = GetFramebuffer(client_id);
3742 if (!group_->bind_generates_resource()) {
3744 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3745 current_decoder_error_ = error::kGenericError;
3749 // It's a new id so make a framebuffer framebuffer for it.
3750 glGenFramebuffersEXT(1, &service_id);
3751 CreateFramebuffer(client_id, service_id);
3752 framebuffer = GetFramebuffer(client_id);
3753 IdAllocatorInterface* id_allocator =
3754 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3755 id_allocator->MarkAsUsed(client_id);
3757 service_id = framebuffer->service_id();
3759 framebuffer->MarkAsValid();
3761 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
3763 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3764 framebuffer_state_.bound_draw_framebuffer = framebuffer;
3766 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3767 framebuffer_state_.bound_read_framebuffer = framebuffer;
3770 framebuffer_state_.clear_state_dirty = true;
3772 // If we are rendering to the backbuffer get the FBO id for any simulated
3774 if (framebuffer == NULL) {
3775 service_id = GetBackbufferServiceId();
3778 glBindFramebufferEXT(target, service_id);
3782 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3783 Renderbuffer* renderbuffer = NULL;
3784 GLuint service_id = 0;
3785 if (client_id != 0) {
3786 renderbuffer = GetRenderbuffer(client_id);
3787 if (!renderbuffer) {
3788 if (!group_->bind_generates_resource()) {
3790 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3791 current_decoder_error_ = error::kGenericError;
3795 // It's a new id so make a renderbuffer renderbuffer for it.
3796 glGenRenderbuffersEXT(1, &service_id);
3797 CreateRenderbuffer(client_id, service_id);
3798 renderbuffer = GetRenderbuffer(client_id);
3799 IdAllocatorInterface* id_allocator =
3800 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3801 id_allocator->MarkAsUsed(client_id);
3803 service_id = renderbuffer->service_id();
3805 renderbuffer->MarkAsValid();
3807 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
3808 state_.bound_renderbuffer = renderbuffer;
3809 glBindRenderbufferEXT(target, service_id);
3812 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
3813 TextureRef* texture_ref = NULL;
3814 GLuint service_id = 0;
3815 if (client_id != 0) {
3816 texture_ref = GetTexture(client_id);
3818 if (!group_->bind_generates_resource()) {
3819 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3820 current_decoder_error_ = error::kGenericError;
3824 // It's a new id so make a texture texture for it.
3825 glGenTextures(1, &service_id);
3826 DCHECK_NE(0u, service_id);
3827 CreateTexture(client_id, service_id);
3828 texture_ref = GetTexture(client_id);
3829 IdAllocatorInterface* id_allocator =
3830 group_->GetIdAllocator(id_namespaces::kTextures);
3831 id_allocator->MarkAsUsed(client_id);
3834 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
3836 Texture* texture = texture_ref->texture();
3838 // Check the texture exists
3839 // Check that we are not trying to bind it to a different target.
3840 if (texture->target() != 0 && texture->target() != target) {
3842 GL_INVALID_OPERATION,
3843 "glBindTexture", "texture bound to more than 1 target.");
3846 if (texture->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3848 GL_INVALID_OPERATION,
3849 "glBindTexture", "illegal target for stream texture.");
3852 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3853 if (texture->target() == 0) {
3854 texture_manager()->SetTarget(texture_ref, target);
3856 glBindTexture(target, texture->service_id());
3858 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
3859 unit.bind_target = target;
3862 unit.bound_texture_2d = texture_ref;
3864 case GL_TEXTURE_CUBE_MAP:
3865 unit.bound_texture_cube_map = texture_ref;
3867 case GL_TEXTURE_EXTERNAL_OES:
3868 unit.bound_texture_external_oes = texture_ref;
3870 case GL_TEXTURE_RECTANGLE_ARB:
3871 unit.bound_texture_rectangle_arb = texture_ref;
3874 NOTREACHED(); // Validation should prevent us getting here.
3879 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
3880 if (state_.vertex_attrib_manager->Enable(index, false)) {
3882 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
3883 glDisableVertexAttribArray(index);
3888 "glDisableVertexAttribArray", "index out of range");
3892 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3893 GLsizei numAttachments,
3894 const GLenum* attachments) {
3895 if (!features().ext_discard_framebuffer) {
3896 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3897 "glDiscardFramebufferEXT",
3898 "function not available");
3902 Framebuffer* framebuffer =
3903 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3905 // Validates the attachments. If one of them fails
3906 // the whole command fails.
3907 for (GLsizei i = 0; i < numAttachments; ++i) {
3909 !validators_->attachment.IsValid(attachments[i])) ||
3911 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
3912 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3913 "glDiscardFramebufferEXT", attachments[i], "attachments");
3918 // Marks each one of them as not cleared
3919 for (GLsizei i = 0; i < numAttachments; ++i) {
3921 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
3926 switch (attachments[i]) {
3928 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
3931 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
3932 case GL_STENCIL_EXT:
3933 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
3942 // If the default framebuffer is bound but we are still rendering to an
3943 // FBO, translate attachment names that refer to default framebuffer
3944 // channels to corresponding framebuffer attachments.
3945 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
3946 for (GLsizei i = 0; i < numAttachments; ++i) {
3947 GLenum attachment = attachments[i];
3948 if (!framebuffer && GetBackbufferServiceId()) {
3949 switch (attachment) {
3951 attachment = GL_COLOR_ATTACHMENT0;
3954 attachment = GL_DEPTH_ATTACHMENT;
3956 case GL_STENCIL_EXT:
3957 attachment = GL_STENCIL_ATTACHMENT;
3964 translated_attachments[i] = attachment;
3967 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
3970 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
3971 if (state_.vertex_attrib_manager->Enable(index, true)) {
3972 glEnableVertexAttribArray(index);
3975 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
3979 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
3980 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3983 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
3985 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
3989 if (target == GL_TEXTURE_CUBE_MAP) {
3990 for (int i = 0; i < 6; ++i) {
3991 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
3992 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
3994 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
3999 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4001 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4006 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4007 // Workaround for Mac driver bug. In the large scheme of things setting
4008 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4009 // hit so there's probably no need to make this conditional. The bug appears
4010 // to be that if the filtering mode is set to something that doesn't require
4011 // mipmaps for rendering, or is never set to something other than the default,
4012 // then glGenerateMipmap misbehaves.
4013 if (workarounds().set_texture_filter_before_generating_mipmap) {
4014 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4016 glGenerateMipmapEXT(target);
4017 if (workarounds().set_texture_filter_before_generating_mipmap) {
4018 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4019 texture_ref->texture()->min_filter());
4021 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4022 if (error == GL_NO_ERROR) {
4023 texture_manager()->MarkMipmapsGenerated(texture_ref);
4027 bool GLES2DecoderImpl::GetHelper(
4028 GLenum pname, GLint* params, GLsizei* num_written) {
4029 DCHECK(num_written);
4030 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4032 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4035 *params = GL_RGBA; // We don't support other formats.
4038 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4041 *params = GL_UNSIGNED_BYTE; // We don't support other types.
4044 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4047 *params = group_->max_fragment_uniform_vectors();
4050 case GL_MAX_VARYING_VECTORS:
4053 *params = group_->max_varying_vectors();
4056 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4059 *params = group_->max_vertex_uniform_vectors();
4065 case GL_MAX_VIEWPORT_DIMS:
4066 if (offscreen_target_frame_buffer_.get()) {
4069 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4070 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4075 case GL_MAX_SAMPLES:
4078 params[0] = renderbuffer_manager()->max_samples();
4081 case GL_MAX_RENDERBUFFER_SIZE:
4084 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4087 case GL_MAX_TEXTURE_SIZE:
4090 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4093 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4096 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4099 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4102 params[0] = group_->max_color_attachments();
4105 case GL_MAX_DRAW_BUFFERS_ARB:
4108 params[0] = group_->max_draw_buffers();
4115 glGetIntegerv(GL_ALPHA_BITS, &v);
4116 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4123 glGetIntegerv(GL_DEPTH_BITS, &v);
4124 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4127 case GL_STENCIL_BITS:
4131 glGetIntegerv(GL_STENCIL_BITS, &v);
4132 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4135 case GL_COMPRESSED_TEXTURE_FORMATS:
4136 *num_written = validators_->compressed_texture_format.GetValues().size();
4138 for (GLint ii = 0; ii < *num_written; ++ii) {
4139 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4143 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4146 *params = validators_->compressed_texture_format.GetValues().size();
4149 case GL_NUM_SHADER_BINARY_FORMATS:
4152 *params = validators_->shader_binary_format.GetValues().size();
4155 case GL_SHADER_BINARY_FORMATS:
4156 *num_written = validators_->shader_binary_format.GetValues().size();
4158 for (GLint ii = 0; ii < *num_written; ++ii) {
4159 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4163 case GL_SHADER_COMPILER:
4169 case GL_ARRAY_BUFFER_BINDING:
4172 if (state_.bound_array_buffer.get()) {
4173 GLuint client_id = 0;
4174 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4176 *params = client_id;
4182 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4185 if (state_.vertex_attrib_manager->element_array_buffer()) {
4186 GLuint client_id = 0;
4187 buffer_manager()->GetClientId(
4188 state_.vertex_attrib_manager->element_array_buffer()->
4189 service_id(), &client_id);
4190 *params = client_id;
4196 case GL_FRAMEBUFFER_BINDING:
4197 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4200 Framebuffer* framebuffer =
4201 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4203 GLuint client_id = 0;
4204 framebuffer_manager()->GetClientId(
4205 framebuffer->service_id(), &client_id);
4206 *params = client_id;
4212 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4215 Framebuffer* framebuffer =
4216 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4218 GLuint client_id = 0;
4219 framebuffer_manager()->GetClientId(
4220 framebuffer->service_id(), &client_id);
4221 *params = client_id;
4227 case GL_RENDERBUFFER_BINDING:
4230 Renderbuffer* renderbuffer =
4231 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4233 *params = renderbuffer->client_id();
4239 case GL_CURRENT_PROGRAM:
4242 if (state_.current_program.get()) {
4243 GLuint client_id = 0;
4244 program_manager()->GetClientId(
4245 state_.current_program->service_id(), &client_id);
4246 *params = client_id;
4252 case GL_VERTEX_ARRAY_BINDING_OES:
4255 if (state_.vertex_attrib_manager.get() !=
4256 default_vertex_attrib_manager_.get()) {
4257 GLuint client_id = 0;
4258 vertex_array_manager_->GetClientId(
4259 state_.vertex_attrib_manager->service_id(), &client_id);
4260 *params = client_id;
4266 case GL_TEXTURE_BINDING_2D:
4269 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4270 if (unit.bound_texture_2d.get()) {
4271 *params = unit.bound_texture_2d->client_id();
4277 case GL_TEXTURE_BINDING_CUBE_MAP:
4280 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4281 if (unit.bound_texture_cube_map.get()) {
4282 *params = unit.bound_texture_cube_map->client_id();
4288 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4291 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4292 if (unit.bound_texture_external_oes.get()) {
4293 *params = unit.bound_texture_external_oes->client_id();
4299 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4302 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4303 if (unit.bound_texture_rectangle_arb.get()) {
4304 *params = unit.bound_texture_rectangle_arb->client_id();
4310 case GL_UNPACK_FLIP_Y_CHROMIUM:
4313 params[0] = unpack_flip_y_;
4316 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4319 params[0] = unpack_premultiply_alpha_;
4322 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4325 params[0] = unpack_unpremultiply_alpha_;
4329 if (pname >= GL_DRAW_BUFFER0_ARB &&
4330 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4333 Framebuffer* framebuffer =
4334 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4336 params[0] = framebuffer->GetDrawBuffer(pname);
4337 } else { // backbuffer
4338 if (pname == GL_DRAW_BUFFER0_ARB)
4339 params[0] = group_->draw_buffer();
4341 params[0] = GL_NONE;
4346 *num_written = util_.GLGetNumValuesReturned(pname);
4351 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4352 GLenum pname, GLsizei* num_values) {
4353 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4356 return GetHelper(pname, NULL, num_values);
4359 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4360 if (GL_MAX_SAMPLES == pname &&
4361 features().use_img_for_multisampled_render_to_texture) {
4362 return GL_MAX_SAMPLES_IMG;
4367 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4369 GLsizei num_written = 0;
4370 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4371 scoped_ptr<GLint[]> values(new GLint[num_written]);
4372 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4373 GetHelper(pname, values.get(), &num_written);
4375 for (GLsizei ii = 0; ii < num_written; ++ii) {
4376 params[ii] = static_cast<GLboolean>(values[ii]);
4379 pname = AdjustGetPname(pname);
4380 glGetBooleanv(pname, params);
4384 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4386 GLsizei num_written = 0;
4387 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4388 if (GetHelper(pname, NULL, &num_written)) {
4389 scoped_ptr<GLint[]> values(new GLint[num_written]);
4390 GetHelper(pname, values.get(), &num_written);
4391 for (GLsizei ii = 0; ii < num_written; ++ii) {
4392 params[ii] = static_cast<GLfloat>(values[ii]);
4395 pname = AdjustGetPname(pname);
4396 glGetFloatv(pname, params);
4401 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4403 GLsizei num_written;
4404 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4405 !GetHelper(pname, params, &num_written)) {
4406 pname = AdjustGetPname(pname);
4407 glGetIntegerv(pname, params);
4411 void GLES2DecoderImpl::DoGetProgramiv(
4412 GLuint program_id, GLenum pname, GLint* params) {
4413 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4417 program->GetProgramiv(pname, params);
4420 void GLES2DecoderImpl::DoGetBufferParameteriv(
4421 GLenum target, GLenum pname, GLint* params) {
4422 // Just delegate it. Some validation is actually done before this.
4423 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4424 &state_, target, pname, params);
4427 void GLES2DecoderImpl::DoBindAttribLocation(
4428 GLuint program_id, GLuint index, const char* name) {
4429 if (!StringIsValidForGLES(name)) {
4431 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4434 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4436 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4439 if (index >= group_->max_vertex_attribs()) {
4441 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4444 Program* program = GetProgramInfoNotShader(
4445 program_id, "glBindAttribLocation");
4449 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4450 glBindAttribLocation(program->service_id(), index, name);
4453 error::Error GLES2DecoderImpl::HandleBindAttribLocation(
4454 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
4455 GLuint program = static_cast<GLuint>(c.program);
4456 GLuint index = static_cast<GLuint>(c.index);
4457 uint32 name_size = c.data_size;
4458 const char* name = GetSharedMemoryAs<const char*>(
4459 c.name_shm_id, c.name_shm_offset, name_size);
4461 return error::kOutOfBounds;
4463 String name_str(name, name_size);
4464 DoBindAttribLocation(program, index, name_str.c_str());
4465 return error::kNoError;
4468 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4469 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4470 GLuint program = static_cast<GLuint>(c.program);
4471 GLuint index = static_cast<GLuint>(c.index);
4472 Bucket* bucket = GetBucket(c.name_bucket_id);
4473 if (!bucket || bucket->size() == 0) {
4474 return error::kInvalidArguments;
4476 std::string name_str;
4477 if (!bucket->GetAsString(&name_str)) {
4478 return error::kInvalidArguments;
4480 DoBindAttribLocation(program, index, name_str.c_str());
4481 return error::kNoError;
4484 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4485 GLuint program_id, GLint location, const char* name) {
4486 if (!StringIsValidForGLES(name)) {
4489 "glBindUniformLocationCHROMIUM", "Invalid character");
4492 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4494 GL_INVALID_OPERATION,
4495 "glBindUniformLocationCHROMIUM", "reserved prefix");
4498 if (location < 0 || static_cast<uint32>(location) >=
4499 (group_->max_fragment_uniform_vectors() +
4500 group_->max_vertex_uniform_vectors()) * 4) {
4503 "glBindUniformLocationCHROMIUM", "location out of range");
4506 Program* program = GetProgramInfoNotShader(
4507 program_id, "glBindUniformLocationCHROMIUM");
4511 if (!program->SetUniformLocationBinding(name, location)) {
4514 "glBindUniformLocationCHROMIUM", "location out of range");
4518 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4519 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
4520 GLuint program = static_cast<GLuint>(c.program);
4521 GLint location = static_cast<GLint>(c.location);
4522 uint32 name_size = c.data_size;
4523 const char* name = GetSharedMemoryAs<const char*>(
4524 c.name_shm_id, c.name_shm_offset, name_size);
4526 return error::kOutOfBounds;
4528 String name_str(name, name_size);
4529 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4530 return error::kNoError;
4533 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4534 uint32 immediate_data_size,
4535 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4536 GLuint program = static_cast<GLuint>(c.program);
4537 GLint location = static_cast<GLint>(c.location);
4538 Bucket* bucket = GetBucket(c.name_bucket_id);
4539 if (!bucket || bucket->size() == 0) {
4540 return error::kInvalidArguments;
4542 std::string name_str;
4543 if (!bucket->GetAsString(&name_str)) {
4544 return error::kInvalidArguments;
4546 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4547 return error::kNoError;
4550 error::Error GLES2DecoderImpl::HandleDeleteShader(
4551 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4552 GLuint client_id = c.shader;
4554 Shader* shader = GetShader(client_id);
4556 if (!shader->IsDeleted()) {
4557 glDeleteShader(shader->service_id());
4558 shader_manager()->MarkAsDeleted(shader);
4561 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4564 return error::kNoError;
4567 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4568 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4569 GLuint client_id = c.program;
4571 Program* program = GetProgram(client_id);
4573 if (!program->IsDeleted()) {
4574 program_manager()->MarkAsDeleted(shader_manager(), program);
4578 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4581 return error::kNoError;
4584 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4585 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4586 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4587 for (GLsizei ii = 0; ii < n; ++ii) {
4588 id_allocator->FreeID(ids[ii]);
4592 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4593 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4594 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4595 GLsizei n = static_cast<GLsizei>(c.n);
4597 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4598 return error::kOutOfBounds;
4600 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4601 c.ids_shm_id, c.ids_shm_offset, data_size);
4603 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4604 return error::kNoError;
4607 return error::kOutOfBounds;
4609 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4610 return error::kNoError;
4613 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4614 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4615 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4616 if (id_offset == 0) {
4617 for (GLsizei ii = 0; ii < n; ++ii) {
4618 ids[ii] = id_allocator->AllocateID();
4621 for (GLsizei ii = 0; ii < n; ++ii) {
4622 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4623 id_offset = ids[ii] + 1;
4628 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4629 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4630 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4631 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4632 GLsizei n = static_cast<GLsizei>(c.n);
4634 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4635 return error::kOutOfBounds;
4637 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4638 c.ids_shm_id, c.ids_shm_offset, data_size);
4640 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4641 return error::kNoError;
4644 return error::kOutOfBounds;
4646 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4647 return error::kNoError;
4650 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4651 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4652 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4653 for (GLsizei ii = 0; ii < n; ++ii) {
4654 if (!id_allocator->MarkAsUsed(ids[ii])) {
4655 for (GLsizei jj = 0; jj < ii; ++jj) {
4656 id_allocator->FreeID(ids[jj]);
4659 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4660 "attempt to register id that already exists");
4666 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4667 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4668 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4669 GLsizei n = static_cast<GLsizei>(c.n);
4671 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4672 return error::kOutOfBounds;
4674 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4675 c.ids_shm_id, c.ids_shm_offset, data_size);
4677 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4678 return error::kNoError;
4681 return error::kOutOfBounds;
4683 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4684 return error::kNoError;
4687 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4688 DCHECK(!ShouldDeferDraws());
4689 if (CheckBoundFramebuffersValid("glClear")) {
4693 return error::kNoError;
4696 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4697 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4698 GLuint client_renderbuffer_id) {
4699 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4702 GL_INVALID_OPERATION,
4703 "glFramebufferRenderbuffer", "no framebuffer bound");
4706 GLuint service_id = 0;
4707 Renderbuffer* renderbuffer = NULL;
4708 if (client_renderbuffer_id) {
4709 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4710 if (!renderbuffer) {
4712 GL_INVALID_OPERATION,
4713 "glFramebufferRenderbuffer", "unknown renderbuffer");
4716 service_id = renderbuffer->service_id();
4718 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4719 glFramebufferRenderbufferEXT(
4720 target, attachment, renderbuffertarget, service_id);
4721 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4722 if (error == GL_NO_ERROR) {
4723 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4725 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4726 framebuffer_state_.clear_state_dirty = true;
4731 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4732 if (SetCapabilityState(cap, false)) {
4737 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4738 if (SetCapabilityState(cap, true)) {
4743 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4744 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4745 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4746 glDepthRange(znear, zfar);
4749 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
4750 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4751 state_.sample_coverage_invert = (invert != 0);
4752 glSampleCoverage(state_.sample_coverage_value, invert);
4755 // Assumes framebuffer is complete.
4756 void GLES2DecoderImpl::ClearUnclearedAttachments(
4757 GLenum target, Framebuffer* framebuffer) {
4758 if (target == GL_READ_FRAMEBUFFER_EXT) {
4759 // bind this to the DRAW point, clear then bind back to READ
4760 // TODO(gman): I don't think there is any guarantee that an FBO that
4761 // is complete on the READ attachment will be complete as a DRAW
4763 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4764 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
4766 GLbitfield clear_bits = 0;
4767 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
4770 (GLES2Util::GetChannelsForFormat(
4771 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4773 glColorMask(true, true, true, true);
4774 clear_bits |= GL_COLOR_BUFFER_BIT;
4777 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4778 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4781 clear_bits |= GL_STENCIL_BUFFER_BIT;
4784 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4785 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4788 clear_bits |= GL_DEPTH_BUFFER_BIT;
4791 glDisable(GL_SCISSOR_TEST);
4792 glClear(clear_bits);
4794 framebuffer_manager()->MarkAttachmentsAsCleared(
4795 framebuffer, renderbuffer_manager(), texture_manager());
4797 RestoreClearState();
4799 if (target == GL_READ_FRAMEBUFFER_EXT) {
4800 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4801 Framebuffer* draw_framebuffer =
4802 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4803 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4804 GetBackbufferServiceId();
4805 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
4809 void GLES2DecoderImpl::RestoreClearState() {
4810 framebuffer_state_.clear_state_dirty = true;
4812 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4813 state_.color_clear_alpha);
4814 glClearStencil(state_.stencil_clear);
4815 glClearDepth(state_.depth_clear);
4816 if (state_.enable_flags.scissor_test) {
4817 glEnable(GL_SCISSOR_TEST);
4821 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
4822 Framebuffer* framebuffer =
4823 GetFramebufferInfoForTarget(target);
4825 return GL_FRAMEBUFFER_COMPLETE;
4827 GLenum completeness = framebuffer->IsPossiblyComplete();
4828 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4829 return completeness;
4831 return framebuffer->GetStatus(texture_manager(), target);
4834 void GLES2DecoderImpl::DoFramebufferTexture2D(
4835 GLenum target, GLenum attachment, GLenum textarget,
4836 GLuint client_texture_id, GLint level) {
4837 DoFramebufferTexture2DCommon(
4838 "glFramebufferTexture2D", target, attachment,
4839 textarget, client_texture_id, level, 0);
4842 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
4843 GLenum target, GLenum attachment, GLenum textarget,
4844 GLuint client_texture_id, GLint level, GLsizei samples) {
4845 if (!features().multisampled_render_to_texture) {
4847 GL_INVALID_OPERATION,
4848 "glFramebufferTexture2DMultisample", "function not available");
4851 DoFramebufferTexture2DCommon(
4852 "glFramebufferTexture2DMultisample", target, attachment,
4853 textarget, client_texture_id, level, samples);
4856 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
4857 const char* name, GLenum target, GLenum attachment, GLenum textarget,
4858 GLuint client_texture_id, GLint level, GLsizei samples) {
4859 if (samples > renderbuffer_manager()->max_samples()) {
4862 "glFramebufferTexture2DMultisample", "samples too large");
4865 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4868 GL_INVALID_OPERATION,
4869 name, "no framebuffer bound.");
4872 GLuint service_id = 0;
4873 TextureRef* texture_ref = NULL;
4874 if (client_texture_id) {
4875 texture_ref = GetTexture(client_texture_id);
4878 GL_INVALID_OPERATION,
4879 name, "unknown texture_ref");
4882 service_id = texture_ref->service_id();
4885 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
4888 name, "level out of range");
4893 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
4895 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
4897 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4899 if (features().use_img_for_multisampled_render_to_texture) {
4900 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
4901 service_id, level, samples);
4903 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
4904 service_id, level, samples);
4907 GLenum error = LOCAL_PEEK_GL_ERROR(name);
4908 if (error == GL_NO_ERROR) {
4909 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
4912 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4913 framebuffer_state_.clear_state_dirty = true;
4917 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
4922 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4923 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
4924 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4927 GL_INVALID_OPERATION,
4928 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
4931 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4932 const Framebuffer::Attachment* attachment_object =
4933 framebuffer->GetAttachment(attachment);
4934 *params = attachment_object ? attachment_object->object_name() : 0;
4936 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
4937 features().use_img_for_multisampled_render_to_texture) {
4938 pname = GL_TEXTURE_SAMPLES_IMG;
4940 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
4944 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4945 GLenum target, GLenum pname, GLint* params) {
4946 Renderbuffer* renderbuffer =
4947 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4948 if (!renderbuffer) {
4950 GL_INVALID_OPERATION,
4951 "glGetRenderbufferParameteriv", "no renderbuffer bound");
4955 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4956 *params = renderbuffer->internal_format();
4958 case GL_RENDERBUFFER_WIDTH:
4959 *params = renderbuffer->width();
4961 case GL_RENDERBUFFER_HEIGHT:
4962 *params = renderbuffer->height();
4964 case GL_RENDERBUFFER_SAMPLES_EXT:
4965 if (features().use_img_for_multisampled_render_to_texture) {
4966 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
4969 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
4973 glGetRenderbufferParameterivEXT(target, pname, params);
4978 void GLES2DecoderImpl::DoBlitFramebufferEXT(
4979 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4980 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4981 GLbitfield mask, GLenum filter) {
4982 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
4983 if (!features().chromium_framebuffer_multisample) {
4985 GL_INVALID_OPERATION,
4986 "glBlitFramebufferEXT", "function not available");
4990 if (!CheckBoundFramebuffersValid("glBlitFramebufferEXT")) {
4994 glDisable(GL_SCISSOR_TEST);
4996 glBlitFramebufferANGLE(
4997 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4999 glBlitFramebufferEXT(
5000 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5002 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
5005 void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
5006 GLenum target, GLsizei samples, GLenum internalformat,
5007 GLsizei width, GLsizei height) {
5008 if (!features().chromium_framebuffer_multisample &&
5009 !features().multisampled_render_to_texture) {
5011 GL_INVALID_OPERATION,
5012 "glRenderbufferStorageMultisample", "function not available");
5016 Renderbuffer* renderbuffer =
5017 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5018 if (!renderbuffer) {
5020 GL_INVALID_OPERATION,
5021 "glRenderbufferStorageMultisample", "no renderbuffer bound");
5025 if (samples > renderbuffer_manager()->max_samples()) {
5028 "glRenderbufferStorageMultisample", "samples too large");
5032 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5033 height > renderbuffer_manager()->max_renderbuffer_size()) {
5036 "glRenderbufferStorageMultisample", "dimensions too large");
5040 uint32 estimated_size = 0;
5041 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5042 width, height, samples, internalformat, &estimated_size)) {
5045 "glRenderbufferStorageMultsample", "dimensions too large");
5049 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5052 "glRenderbufferStorageMultsample", "out of memory");
5056 GLenum impl_format =
5057 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5059 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample");
5061 glRenderbufferStorageMultisampleANGLE(
5062 target, samples, impl_format, width, height);
5063 } else if (features().use_img_for_multisampled_render_to_texture) {
5064 glRenderbufferStorageMultisampleIMG(
5065 target, samples, impl_format, width, height);
5067 glRenderbufferStorageMultisampleEXT(
5068 target, samples, impl_format, width, height);
5070 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample");
5071 if (error == GL_NO_ERROR) {
5073 if (workarounds().validate_multisample_buffer_allocation) {
5074 if (!VerifyMultisampleRenderbufferIntegrity(
5075 renderbuffer->service_id(), impl_format)) {
5078 "glRenderbufferStorageMultisample", "out of memory");
5083 // TODO(gman): If renderbuffers tracked which framebuffers they were
5084 // attached to we could just mark those framebuffers as not complete.
5085 framebuffer_manager()->IncFramebufferStateChangeCount();
5086 renderbuffer_manager()->SetInfo(
5087 renderbuffer, samples, internalformat, width, height);
5091 // This function validates the allocation of a multisampled renderbuffer
5092 // by clearing it to a key color, blitting the contents to a texture, and
5093 // reading back the color to ensure it matches the key.
5094 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5095 GLuint renderbuffer, GLenum format) {
5097 // Only validate color buffers.
5098 // These formats have been selected because they are very common or are known
5099 // to be used by the WebGL backbuffer. If problems are observed with other
5100 // color formats they can be added here.
5111 GLint draw_framebuffer, read_framebuffer;
5113 // Cache framebuffer and texture bindings.
5114 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5115 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5117 if (!validation_texture_) {
5118 GLint bound_texture;
5119 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5121 // Create additional resources needed for the verification.
5122 glGenTextures(1, &validation_texture_);
5123 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5124 glGenFramebuffersEXT(1, &validation_fbo_);
5126 // Texture only needs to be 1x1.
5127 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5128 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5129 GL_UNSIGNED_BYTE, NULL);
5131 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5132 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5133 GL_TEXTURE_2D, validation_texture_, 0);
5135 glBindTexture(GL_TEXTURE_2D, bound_texture);
5138 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5139 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5140 GL_RENDERBUFFER, renderbuffer);
5142 // Cache current state and reset it to the values we require.
5143 GLboolean scissor_enabled = false;
5144 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5145 if (scissor_enabled)
5146 glDisable(GL_SCISSOR_TEST);
5148 GLboolean color_mask[4] = {true, true, true, true};
5149 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5150 glColorMask(true, true, true, true);
5152 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5153 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5154 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5156 // Clear the buffer to the desired key color.
5157 glClear(GL_COLOR_BUFFER_BIT);
5159 // Blit from the multisample buffer to a standard texture.
5160 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5161 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5163 glBlitFramebufferEXT(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5165 // Read a pixel from the buffer.
5166 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5168 unsigned char pixel[3] = {0, 0, 0};
5169 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5171 // Detach the renderbuffer.
5172 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5173 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5174 GL_RENDERBUFFER, 0);
5176 // Restore cached state.
5177 if (scissor_enabled)
5178 glEnable(GL_SCISSOR_TEST);
5180 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5181 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5182 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5183 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5185 // Return true if the pixel matched the desired key color.
5186 return (pixel[0] == 0xFF &&
5191 void GLES2DecoderImpl::DoRenderbufferStorage(
5192 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5193 Renderbuffer* renderbuffer =
5194 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5195 if (!renderbuffer) {
5197 GL_INVALID_OPERATION,
5198 "glRenderbufferStorage", "no renderbuffer bound");
5202 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5203 height > renderbuffer_manager()->max_renderbuffer_size()) {
5205 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5209 uint32 estimated_size = 0;
5210 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5211 width, height, 1, internalformat, &estimated_size)) {
5213 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5217 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5219 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5223 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5224 glRenderbufferStorageEXT(
5226 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5230 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5231 if (error == GL_NO_ERROR) {
5232 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5233 // we could just mark those framebuffers as not complete.
5234 framebuffer_manager()->IncFramebufferStateChangeCount();
5235 renderbuffer_manager()->SetInfo(
5236 renderbuffer, 1, internalformat, width, height);
5240 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5241 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5242 Program* program = GetProgramInfoNotShader(
5243 program_id, "glLinkProgram");
5248 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5249 ShaderTranslator* vertex_translator = NULL;
5250 ShaderTranslator* fragment_translator = NULL;
5251 if (use_shader_translator_) {
5252 vertex_translator = vertex_translator_.get();
5253 fragment_translator = fragment_translator_.get();
5255 if (program->Link(shader_manager(),
5257 fragment_translator,
5258 feature_info_.get(),
5259 shader_cache_callback_)) {
5260 if (program == state_.current_program.get()) {
5261 if (workarounds().use_current_program_after_successful_link) {
5262 glUseProgram(program->service_id());
5264 program_manager()->ClearUniforms(program);
5269 void GLES2DecoderImpl::DoTexParameterf(
5270 GLenum target, GLenum pname, GLfloat param) {
5271 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5274 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5278 texture_manager()->SetParameter(
5279 "glTexParameterf", GetErrorState(), texture, pname,
5280 static_cast<GLint>(param));
5283 void GLES2DecoderImpl::DoTexParameteri(
5284 GLenum target, GLenum pname, GLint param) {
5285 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5288 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5292 texture_manager()->SetParameter(
5293 "glTexParameteri", GetErrorState(), texture, pname, param);
5296 void GLES2DecoderImpl::DoTexParameterfv(
5297 GLenum target, GLenum pname, const GLfloat* params) {
5298 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5301 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5305 texture_manager()->SetParameter(
5306 "glTexParameterfv", GetErrorState(), texture, pname,
5307 static_cast<GLint>(params[0]));
5310 void GLES2DecoderImpl::DoTexParameteriv(
5311 GLenum target, GLenum pname, const GLint* params) {
5312 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5316 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5320 texture_manager()->SetParameter(
5321 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5324 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5325 if (!state_.current_program.get()) {
5326 // The program does not exist.
5328 GL_INVALID_OPERATION, function_name, "no program in use");
5331 if (!state_.current_program->InUse()) {
5333 GL_INVALID_OPERATION, function_name, "program not linked");
5339 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5340 GLint location, const char* function_name) {
5341 if (!CheckCurrentProgram(function_name)) {
5344 return location != -1;
5349 static const GLenum valid_int_vec1_types_list[] = {
5353 GL_SAMPLER_2D_RECT_ARB,
5355 GL_SAMPLER_EXTERNAL_OES,
5358 static const GLenum valid_int_vec2_types_list[] = {
5363 static const GLenum valid_int_vec3_types_list[] = {
5368 static const GLenum valid_int_vec4_types_list[] = {
5373 static const GLenum valid_float_vec1_types_list[] = {
5378 static const GLenum valid_float_vec2_types_list[] = {
5383 static const GLenum valid_float_vec3_types_list[] = {
5388 static const GLenum valid_float_vec4_types_list[] = {
5393 static const GLenum valid_float_mat2_types_list[] = {
5397 static const GLenum valid_float_mat3_types_list[] = {
5401 static const GLenum valid_float_mat4_types_list[] = {
5405 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5406 valid_int_vec1_types_list,
5407 arraysize(valid_int_vec1_types_list),
5410 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5411 valid_int_vec2_types_list,
5412 arraysize(valid_int_vec2_types_list),
5415 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5416 valid_int_vec3_types_list,
5417 arraysize(valid_int_vec3_types_list),
5420 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5421 valid_int_vec4_types_list,
5422 arraysize(valid_int_vec4_types_list),
5425 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5426 valid_float_vec1_types_list,
5427 arraysize(valid_float_vec1_types_list),
5430 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5431 valid_float_vec2_types_list,
5432 arraysize(valid_float_vec2_types_list),
5435 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5436 valid_float_vec3_types_list,
5437 arraysize(valid_float_vec3_types_list),
5440 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5441 valid_float_vec4_types_list,
5442 arraysize(valid_float_vec4_types_list),
5445 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5446 valid_float_mat2_types_list,
5447 arraysize(valid_float_mat2_types_list),
5450 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5451 valid_float_mat3_types_list,
5452 arraysize(valid_float_mat3_types_list),
5455 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5456 valid_float_mat4_types_list,
5457 arraysize(valid_float_mat4_types_list),
5460 } // anonymous namespace.
5462 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5463 GLint fake_location, const char* function_name,
5464 const GLES2DecoderImpl::BaseUniformInfo& base_info,
5465 GLint* real_location, GLenum* type, GLsizei* count) {
5468 DCHECK(real_location);
5470 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5473 GLint array_index = -1;
5474 const Program::UniformInfo* info =
5475 state_.current_program->GetUniformInfoByFakeLocation(
5476 fake_location, real_location, &array_index);
5479 GL_INVALID_OPERATION, function_name, "unknown location");
5483 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5484 if (base_info.valid_types[ii] == info->type) {
5491 GL_INVALID_OPERATION, function_name,
5492 "wrong uniform function for type");
5495 if (*count > 1 && !info->is_array) {
5497 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5500 *count = std::min(info->size - array_index, *count);
5508 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5511 GLint real_location = -1;
5512 if (!PrepForSetUniformByLocation(
5513 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5514 &real_location, &type, &count)) {
5517 if (!state_.current_program->SetSamplers(
5518 state_.texture_units.size(), fake_location, 1, &v0)) {
5520 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5523 glUniform1i(real_location, v0);
5526 void GLES2DecoderImpl::DoUniform1iv(
5527 GLint fake_location, GLsizei count, const GLint *value) {
5529 GLint real_location = -1;
5530 if (!PrepForSetUniformByLocation(
5531 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5532 &real_location, &type, &count)) {
5535 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5536 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5537 if (!state_.current_program->SetSamplers(
5538 state_.texture_units.size(), fake_location, count, value)) {
5540 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5544 glUniform1iv(real_location, count, value);
5547 void GLES2DecoderImpl::DoUniform1fv(
5548 GLint fake_location, GLsizei count, const GLfloat* value) {
5550 GLint real_location = -1;
5551 if (!PrepForSetUniformByLocation(
5552 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5553 &real_location, &type, &count)) {
5556 if (type == GL_BOOL) {
5557 scoped_ptr<GLint[]> temp(new GLint[count]);
5558 for (GLsizei ii = 0; ii < count; ++ii) {
5559 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5561 DoUniform1iv(real_location, count, temp.get());
5563 glUniform1fv(real_location, count, value);
5567 void GLES2DecoderImpl::DoUniform2fv(
5568 GLint fake_location, GLsizei count, const GLfloat* value) {
5570 GLint real_location = -1;
5571 if (!PrepForSetUniformByLocation(
5572 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5573 &real_location, &type, &count)) {
5576 if (type == GL_BOOL_VEC2) {
5577 GLsizei num_values = count * 2;
5578 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5579 for (GLsizei ii = 0; ii < num_values; ++ii) {
5580 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5582 glUniform2iv(real_location, count, temp.get());
5584 glUniform2fv(real_location, count, value);
5588 void GLES2DecoderImpl::DoUniform3fv(
5589 GLint fake_location, GLsizei count, const GLfloat* value) {
5591 GLint real_location = -1;
5592 if (!PrepForSetUniformByLocation(
5593 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5594 &real_location, &type, &count)) {
5597 if (type == GL_BOOL_VEC3) {
5598 GLsizei num_values = count * 3;
5599 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5600 for (GLsizei ii = 0; ii < num_values; ++ii) {
5601 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5603 glUniform3iv(real_location, count, temp.get());
5605 glUniform3fv(real_location, count, value);
5609 void GLES2DecoderImpl::DoUniform4fv(
5610 GLint fake_location, GLsizei count, const GLfloat* value) {
5612 GLint real_location = -1;
5613 if (!PrepForSetUniformByLocation(
5614 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5615 &real_location, &type, &count)) {
5618 if (type == GL_BOOL_VEC4) {
5619 GLsizei num_values = count * 4;
5620 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5621 for (GLsizei ii = 0; ii < num_values; ++ii) {
5622 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5624 glUniform4iv(real_location, count, temp.get());
5626 glUniform4fv(real_location, count, value);
5630 void GLES2DecoderImpl::DoUniform2iv(
5631 GLint fake_location, GLsizei count, const GLint* value) {
5633 GLint real_location = -1;
5634 if (!PrepForSetUniformByLocation(
5635 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5636 &real_location, &type, &count)) {
5639 glUniform2iv(real_location, count, value);
5642 void GLES2DecoderImpl::DoUniform3iv(
5643 GLint fake_location, GLsizei count, const GLint* value) {
5645 GLint real_location = -1;
5646 if (!PrepForSetUniformByLocation(
5647 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5648 &real_location, &type, &count)) {
5651 glUniform3iv(real_location, count, value);
5654 void GLES2DecoderImpl::DoUniform4iv(
5655 GLint fake_location, GLsizei count, const GLint* value) {
5657 GLint real_location = -1;
5658 if (!PrepForSetUniformByLocation(
5659 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5660 &real_location, &type, &count)) {
5663 glUniform4iv(real_location, count, value);
5666 void GLES2DecoderImpl::DoUniformMatrix2fv(
5667 GLint fake_location, GLsizei count, GLboolean transpose,
5668 const GLfloat* value) {
5670 GLint real_location = -1;
5671 if (!PrepForSetUniformByLocation(
5672 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5673 &real_location, &type, &count)) {
5676 glUniformMatrix2fv(real_location, count, transpose, value);
5679 void GLES2DecoderImpl::DoUniformMatrix3fv(
5680 GLint fake_location, GLsizei count, GLboolean transpose,
5681 const GLfloat* value) {
5683 GLint real_location = -1;
5684 if (!PrepForSetUniformByLocation(
5685 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5686 &real_location, &type, &count)) {
5689 glUniformMatrix3fv(real_location, count, transpose, value);
5692 void GLES2DecoderImpl::DoUniformMatrix4fv(
5693 GLint fake_location, GLsizei count, GLboolean transpose,
5694 const GLfloat* value) {
5696 GLint real_location = -1;
5697 if (!PrepForSetUniformByLocation(
5698 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5699 &real_location, &type, &count)) {
5702 glUniformMatrix4fv(real_location, count, transpose, value);
5705 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5706 GLuint service_id = 0;
5707 Program* program = NULL;
5709 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5713 if (!program->IsValid()) {
5714 // Program was not linked successfully. (ie, glLinkProgram)
5716 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5719 service_id = program->service_id();
5721 if (state_.current_program.get()) {
5722 program_manager()->UnuseProgram(shader_manager(),
5723 state_.current_program.get());
5725 state_.current_program = program;
5726 LogClientServiceMapping("glUseProgram", program_id, service_id);
5727 glUseProgram(service_id);
5728 if (state_.current_program.get()) {
5729 program_manager()->UseProgram(state_.current_program.get());
5733 void GLES2DecoderImpl::RenderWarning(
5734 const char* filename, int line, const std::string& msg) {
5735 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
5738 void GLES2DecoderImpl::PerformanceWarning(
5739 const char* filename, int line, const std::string& msg) {
5740 logger_.LogMessage(filename, line,
5741 std::string("PERFORMANCE WARNING: ") + msg);
5744 void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture,
5745 GLuint texture_unit_index) {
5746 if (texture && texture->IsStreamTexture()) {
5747 DCHECK(stream_texture_manager());
5748 StreamTexture* stream_tex =
5749 stream_texture_manager()->LookupStreamTexture(texture->service_id());
5751 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5752 stream_tex->Update();
5757 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5758 Texture* texture, GLenum textarget) {
5759 // This might be supported in the future.
5760 if (textarget != GL_TEXTURE_2D)
5762 // Image is already in use if texture is attached to a framebuffer.
5763 if (texture && !texture->IsAttachedToFramebuffer()) {
5764 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5766 ScopedGLErrorSuppressor suppressor(
5767 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5769 glBindTexture(textarget, texture->service_id());
5770 image->WillUseTexImage();
5771 RestoreCurrentTexture2DBindings(&state_);
5776 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
5777 Texture* texture, GLenum textarget) {
5778 // This might be supported in the future.
5779 if (textarget != GL_TEXTURE_2D)
5781 // Image is still in use if texture is attached to a framebuffer.
5782 if (texture && !texture->IsAttachedToFramebuffer()) {
5783 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5785 ScopedGLErrorSuppressor suppressor(
5786 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
5788 glBindTexture(textarget, texture->service_id());
5789 image->DidUseTexImage();
5790 RestoreCurrentTexture2DBindings(&state_);
5795 bool GLES2DecoderImpl::PrepareTexturesForRender() {
5796 DCHECK(state_.current_program.get());
5797 if (!texture_manager()->HaveUnrenderableTextures() &&
5798 !texture_manager()->HaveImages() &&
5799 !features().oes_egl_image_external) {
5803 bool textures_set = false;
5804 const Program::SamplerIndices& sampler_indices =
5805 state_.current_program->sampler_indices();
5806 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5807 const Program::UniformInfo* uniform_info =
5808 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5809 DCHECK(uniform_info);
5810 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5811 GLuint texture_unit_index = uniform_info->texture_units[jj];
5812 if (texture_unit_index < state_.texture_units.size()) {
5813 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5814 TextureRef* texture_ref =
5815 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5816 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
5817 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
5818 textures_set = true;
5819 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5822 texture_manager()->black_texture_id(uniform_info->type));
5823 LOCAL_RENDER_WARNING(
5824 std::string("texture bound to texture unit ") +
5825 base::IntToString(texture_unit_index) +
5826 " is not renderable. It maybe non-power-of-2 and have"
5827 " incompatible texture filtering or is not"
5828 " 'texture complete'");
5832 Texture* texture = texture_ref->texture();
5833 if (textarget == GL_TEXTURE_2D) {
5834 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5835 if (image && !texture->IsAttachedToFramebuffer()) {
5836 ScopedGLErrorSuppressor suppressor(
5837 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
5838 textures_set = true;
5839 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5840 image->WillUseTexImage();
5845 UpdateStreamTextureIfNeeded(texture, texture_unit_index);
5847 // else: should this be an error?
5850 return !textures_set;
5853 void GLES2DecoderImpl::RestoreStateForTextures() {
5854 DCHECK(state_.current_program.get());
5855 const Program::SamplerIndices& sampler_indices =
5856 state_.current_program->sampler_indices();
5857 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5858 const Program::UniformInfo* uniform_info =
5859 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5860 DCHECK(uniform_info);
5861 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5862 GLuint texture_unit_index = uniform_info->texture_units[jj];
5863 if (texture_unit_index < state_.texture_units.size()) {
5864 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5865 TextureRef* texture_ref =
5866 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5867 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
5868 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5869 // Get the texture_ref info that was previously bound here.
5870 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
5871 ? texture_unit.bound_texture_2d.get()
5872 : texture_unit.bound_texture_cube_map.get();
5873 glBindTexture(texture_unit.bind_target,
5874 texture_ref ? texture_ref->service_id() : 0);
5878 Texture* texture = texture_ref->texture();
5879 if (texture_unit.bind_target == GL_TEXTURE_2D) {
5880 gfx::GLImage* image = texture->GetLevelImage(
5881 texture_unit.bind_target, 0);
5882 if (image && !texture->IsAttachedToFramebuffer()) {
5883 ScopedGLErrorSuppressor suppressor(
5884 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
5885 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5886 image->DidUseTexImage();
5893 // Set the active texture back to whatever the user had it as.
5894 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
5897 bool GLES2DecoderImpl::ClearUnclearedTextures() {
5898 // Only check if there are some uncleared textures.
5899 if (!texture_manager()->HaveUnsafeTextures()) {
5903 // 1: Check all textures we are about to render with.
5904 if (state_.current_program.get()) {
5905 const Program::SamplerIndices& sampler_indices =
5906 state_.current_program->sampler_indices();
5907 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5908 const Program::UniformInfo* uniform_info =
5909 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5910 DCHECK(uniform_info);
5911 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5912 GLuint texture_unit_index = uniform_info->texture_units[jj];
5913 if (texture_unit_index < state_.texture_units.size()) {
5914 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
5915 TextureRef* texture_ref =
5916 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
5917 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
5918 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
5929 bool GLES2DecoderImpl::IsDrawValid(
5930 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
5931 // NOTE: We specifically do not check current_program->IsValid() because
5932 // it could never be invalid since glUseProgram would have failed. While
5933 // glLinkProgram could later mark the program as invalid the previous
5934 // valid program will still function if it is still the current program.
5935 if (!state_.current_program.get()) {
5936 // The program does not exist.
5937 // But GL says no ERROR.
5938 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
5942 return state_.vertex_attrib_manager
5943 ->ValidateBindings(function_name,
5945 feature_info_.get(),
5946 state_.current_program.get(),
5947 max_vertex_accessed,
5951 bool GLES2DecoderImpl::SimulateAttrib0(
5952 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
5956 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5959 const VertexAttrib* attrib =
5960 state_.vertex_attrib_manager->GetVertexAttrib(0);
5961 // If it's enabled or it's not used then we don't need to do anything.
5962 bool attrib_0_used =
5963 state_.current_program->GetAttribInfoByLocation(0) != NULL;
5964 if (attrib->enabled() && attrib_0_used) {
5968 // Make a buffer with a single repeated vec4 value enough to
5969 // simulate the constant value that is supposed to be here.
5970 // This is required to emulate GLES2 on GL.
5971 GLuint num_vertices = max_vertex_accessed + 1;
5972 uint32 size_needed = 0;
5974 if (num_vertices == 0 ||
5975 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
5976 size_needed > 0x7FFFFFFFU) {
5977 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
5981 LOCAL_PERFORMANCE_WARNING(
5982 "Attribute 0 is disabled. This has signficant performance penalty");
5984 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
5985 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5987 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5989 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
5990 GLenum error = glGetError();
5991 if (error != GL_NO_ERROR) {
5993 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
5998 const Vec4& value = state_.attrib_values[0];
6001 (!attrib_0_buffer_matches_value_ ||
6002 (value.v[0] != attrib_0_value_.v[0] ||
6003 value.v[1] != attrib_0_value_.v[1] ||
6004 value.v[2] != attrib_0_value_.v[2] ||
6005 value.v[3] != attrib_0_value_.v[3])))) {
6006 std::vector<Vec4> temp(num_vertices, value);
6007 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6008 attrib_0_buffer_matches_value_ = true;
6009 attrib_0_value_ = value;
6010 attrib_0_size_ = size_needed;
6013 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6015 if (attrib->divisor())
6016 glVertexAttribDivisorANGLE(0, 0);
6022 void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
6023 const VertexAttrib* attrib =
6024 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6025 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6026 Buffer* buffer = attrib->buffer();
6027 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6028 glVertexAttribPointer(
6029 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6030 attrib->gl_stride(), ptr);
6031 if (attrib->divisor())
6032 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6035 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6038 // Never touch vertex attribute 0's state (in particular, never
6039 // disable it) when running on desktop GL because it will never be
6041 if (attrib_index != 0 ||
6042 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6043 if (attrib->enabled()) {
6044 glEnableVertexAttribArray(attrib_index);
6046 glDisableVertexAttribArray(attrib_index);
6051 bool GLES2DecoderImpl::SimulateFixedAttribs(
6052 const char* function_name,
6053 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6056 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6059 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6063 LOCAL_PERFORMANCE_WARNING(
6064 "GL_FIXED attributes have a signficant performance penalty");
6066 // NOTE: we could be smart and try to check if a buffer is used
6067 // twice in 2 different attribs, find the overlapping parts and therefore
6068 // duplicate the minimum amount of data but this whole code path is not meant
6069 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6070 // tests so we just add to the buffer attrib used.
6072 GLuint elements_needed = 0;
6073 const VertexAttribManager::VertexAttribList& enabled_attribs =
6074 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6075 for (VertexAttribManager::VertexAttribList::const_iterator it =
6076 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6077 const VertexAttrib* attrib = *it;
6078 const Program::VertexAttrib* attrib_info =
6079 state_.current_program->GetAttribInfoByLocation(attrib->index());
6080 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6081 max_vertex_accessed);
6082 GLuint num_vertices = max_accessed + 1;
6083 if (num_vertices == 0) {
6085 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6089 attrib->CanAccess(max_accessed) &&
6090 attrib->type() == GL_FIXED) {
6091 uint32 elements_used = 0;
6092 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6093 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6095 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6101 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6102 uint32 size_needed = 0;
6103 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6104 size_needed > 0x7FFFFFFFU) {
6106 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6112 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6113 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6114 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6115 GLenum error = glGetError();
6116 if (error != GL_NO_ERROR) {
6118 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6123 // Copy the elements and convert to float
6124 GLintptr offset = 0;
6125 for (VertexAttribManager::VertexAttribList::const_iterator it =
6126 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6127 const VertexAttrib* attrib = *it;
6128 const Program::VertexAttrib* attrib_info =
6129 state_.current_program->GetAttribInfoByLocation(attrib->index());
6130 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6131 max_vertex_accessed);
6132 GLuint num_vertices = max_accessed + 1;
6133 if (num_vertices == 0) {
6135 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6139 attrib->CanAccess(max_accessed) &&
6140 attrib->type() == GL_FIXED) {
6141 int num_elements = attrib->size() * kSizeOfFloat;
6142 int size = num_elements * num_vertices;
6143 scoped_ptr<float[]> data(new float[size]);
6144 const int32* src = reinterpret_cast<const int32 *>(
6145 attrib->buffer()->GetRange(attrib->offset(), size));
6146 const int32* end = src + num_elements;
6147 float* dst = data.get();
6148 while (src != end) {
6149 *dst++ = static_cast<float>(*src++) / 65536.0f;
6151 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6152 glVertexAttribPointer(
6153 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6154 reinterpret_cast<GLvoid*>(offset));
6162 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6163 // There's no need to call glVertexAttribPointer because we shadow all the
6164 // settings and passing GL_FIXED to it will not work.
6167 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6171 error::Error GLES2DecoderImpl::DoDrawArrays(
6172 const char* function_name,
6177 GLsizei primcount) {
6178 if (ShouldDeferDraws())
6179 return error::kDeferCommandUntilLater;
6180 if (!validators_->draw_mode.IsValid(mode)) {
6181 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6182 return error::kNoError;
6185 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6186 return error::kNoError;
6188 if (primcount < 0) {
6189 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6190 return error::kNoError;
6192 if (!CheckBoundFramebuffersValid(function_name)) {
6193 return error::kNoError;
6195 // We have to check this here because the prototype for glDrawArrays
6196 // is GLint not GLsizei.
6198 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6199 return error::kNoError;
6202 if (count == 0 || (instanced && primcount == 0)) {
6203 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6204 return error::kNoError;
6207 GLuint max_vertex_accessed = first + count - 1;
6208 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6209 if (!ClearUnclearedTextures()) {
6210 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6211 return error::kNoError;
6213 bool simulated_attrib_0 = false;
6214 if (!SimulateAttrib0(
6215 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6216 return error::kNoError;
6218 bool simulated_fixed_attribs = false;
6219 if (SimulateFixedAttribs(
6220 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6222 bool textures_set = !PrepareTexturesForRender();
6225 glDrawArrays(mode, first, count);
6227 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6229 ProcessPendingQueries();
6231 RestoreStateForTextures();
6233 if (simulated_fixed_attribs) {
6234 RestoreStateForSimulatedFixedAttribs();
6237 if (simulated_attrib_0) {
6238 RestoreStateForAttrib(0);
6241 return error::kNoError;
6244 error::Error GLES2DecoderImpl::HandleDrawArrays(
6245 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6246 return DoDrawArrays("glDrawArrays",
6248 static_cast<GLenum>(c.mode),
6249 static_cast<GLint>(c.first),
6250 static_cast<GLsizei>(c.count),
6254 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6255 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6256 if (!features().angle_instanced_arrays) {
6258 GL_INVALID_OPERATION,
6259 "glDrawArraysInstancedANGLE", "function not available");
6260 return error::kNoError;
6262 return DoDrawArrays("glDrawArraysIntancedANGLE",
6264 static_cast<GLenum>(c.mode),
6265 static_cast<GLint>(c.first),
6266 static_cast<GLsizei>(c.count),
6267 static_cast<GLsizei>(c.primcount));
6270 error::Error GLES2DecoderImpl::DoDrawElements(
6271 const char* function_name,
6277 GLsizei primcount) {
6278 if (ShouldDeferDraws())
6279 return error::kDeferCommandUntilLater;
6280 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6282 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6283 return error::kNoError;
6287 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6288 return error::kNoError;
6291 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6292 return error::kNoError;
6294 if (!validators_->draw_mode.IsValid(mode)) {
6295 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6296 return error::kNoError;
6298 if (!validators_->index_type.IsValid(type)) {
6299 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6300 return error::kNoError;
6302 if (primcount < 0) {
6303 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6304 return error::kNoError;
6307 if (!CheckBoundFramebuffersValid(function_name)) {
6308 return error::kNoError;
6311 if (count == 0 || (instanced && primcount == 0)) {
6312 return error::kNoError;
6315 GLuint max_vertex_accessed;
6316 Buffer* element_array_buffer =
6317 state_.vertex_attrib_manager->element_array_buffer();
6319 if (!element_array_buffer->GetMaxValueForRange(
6320 offset, count, type, &max_vertex_accessed)) {
6322 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6323 return error::kNoError;
6326 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6327 if (!ClearUnclearedTextures()) {
6328 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6329 return error::kNoError;
6331 bool simulated_attrib_0 = false;
6332 if (!SimulateAttrib0(
6333 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6334 return error::kNoError;
6336 bool simulated_fixed_attribs = false;
6337 if (SimulateFixedAttribs(
6338 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6340 bool textures_set = !PrepareTexturesForRender();
6342 // TODO(gman): Refactor to hide these details in BufferManager or
6343 // VertexAttribManager.
6344 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6345 bool used_client_side_array = false;
6346 if (element_array_buffer->IsClientSideArray()) {
6347 used_client_side_array = true;
6348 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6349 indices = element_array_buffer->GetRange(offset, 0);
6353 glDrawElements(mode, count, type, indices);
6355 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6358 if (used_client_side_array) {
6359 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6360 element_array_buffer->service_id());
6363 ProcessPendingQueries();
6365 RestoreStateForTextures();
6367 if (simulated_fixed_attribs) {
6368 RestoreStateForSimulatedFixedAttribs();
6371 if (simulated_attrib_0) {
6372 RestoreStateForAttrib(0);
6375 return error::kNoError;
6378 error::Error GLES2DecoderImpl::HandleDrawElements(
6379 uint32 immediate_data_size, const cmds::DrawElements& c) {
6380 return DoDrawElements("glDrawElements",
6382 static_cast<GLenum>(c.mode),
6383 static_cast<GLsizei>(c.count),
6384 static_cast<GLenum>(c.type),
6385 static_cast<int32>(c.index_offset),
6389 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6390 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6391 if (!features().angle_instanced_arrays) {
6393 GL_INVALID_OPERATION,
6394 "glDrawElementsInstancedANGLE", "function not available");
6395 return error::kNoError;
6397 return DoDrawElements("glDrawElementsInstancedANGLE",
6399 static_cast<GLenum>(c.mode),
6400 static_cast<GLsizei>(c.count),
6401 static_cast<GLenum>(c.type),
6402 static_cast<int32>(c.index_offset),
6403 static_cast<GLsizei>(c.primcount));
6406 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6407 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6408 GLuint max_vertex_accessed = 0;
6409 Buffer* buffer = GetBuffer(buffer_id);
6411 // TODO(gman): Should this be a GL error or a command buffer error?
6413 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6415 if (!buffer->GetMaxValueForRange(
6416 offset, count, type, &max_vertex_accessed)) {
6417 // TODO(gman): Should this be a GL error or a command buffer error?
6419 GL_INVALID_OPERATION,
6420 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6423 return max_vertex_accessed;
6426 // Calls glShaderSource for the various versions of the ShaderSource command.
6427 // Assumes that data / data_size points to a piece of memory that is in range
6428 // of whatever context it came from (shared memory, immediate memory, bucket
6430 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6431 GLuint client_id, const char* data, uint32 data_size) {
6432 std::string str(data, data + data_size);
6433 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6435 return error::kNoError;
6437 // Note: We don't actually call glShaderSource here. We wait until
6438 // the call to glCompileShader.
6439 shader->UpdateSource(str.c_str());
6440 return error::kNoError;
6443 error::Error GLES2DecoderImpl::HandleShaderSource(
6444 uint32 immediate_data_size, const cmds::ShaderSource& c) {
6445 uint32 data_size = c.data_size;
6446 const char* data = GetSharedMemoryAs<const char*>(
6447 c.data_shm_id, c.data_shm_offset, data_size);
6449 return error::kOutOfBounds;
6451 return ShaderSourceHelper(c.shader, data, data_size);
6454 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6455 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6456 Bucket* bucket = GetBucket(c.data_bucket_id);
6457 if (!bucket || bucket->size() == 0) {
6458 return error::kInvalidArguments;
6460 return ShaderSourceHelper(
6461 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6462 bucket->size() - 1);
6465 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6466 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6467 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6471 ShaderTranslator* translator = NULL;
6472 if (use_shader_translator_) {
6473 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6474 vertex_translator_.get() : fragment_translator_.get();
6477 program_manager()->DoCompileShader(shader, translator, feature_info_.get());
6480 void GLES2DecoderImpl::DoGetShaderiv(
6481 GLuint shader_id, GLenum pname, GLint* params) {
6482 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6487 case GL_SHADER_SOURCE_LENGTH:
6488 *params = shader->source() ? shader->source()->size() + 1 : 0;
6490 case GL_COMPILE_STATUS:
6491 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6493 case GL_INFO_LOG_LENGTH:
6494 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6496 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6497 *params = shader->translated_source() ?
6498 shader->translated_source()->size() + 1 : 0;
6503 glGetShaderiv(shader->service_id(), pname, params);
6506 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6507 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6508 GLuint shader_id = c.shader;
6509 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6510 Bucket* bucket = CreateBucket(bucket_id);
6511 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6512 if (!shader || !shader->source()) {
6514 return error::kNoError;
6516 bucket->SetFromString(shader->source()->c_str());
6517 return error::kNoError;
6520 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6521 uint32 immediate_data_size,
6522 const cmds::GetTranslatedShaderSourceANGLE& c) {
6523 GLuint shader_id = c.shader;
6524 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6525 Bucket* bucket = CreateBucket(bucket_id);
6526 Shader* shader = GetShaderInfoNotProgram(
6527 shader_id, "glTranslatedGetShaderSourceANGLE");
6530 return error::kNoError;
6533 bucket->SetFromString(shader->translated_source() ?
6534 shader->translated_source()->c_str() : NULL);
6535 return error::kNoError;
6538 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6539 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6540 GLuint program_id = c.program;
6541 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6542 Bucket* bucket = CreateBucket(bucket_id);
6543 Program* program = GetProgramInfoNotShader(
6544 program_id, "glGetProgramInfoLog");
6545 if (!program || !program->log_info()) {
6546 bucket->SetFromString("");
6547 return error::kNoError;
6549 bucket->SetFromString(program->log_info()->c_str());
6550 return error::kNoError;
6553 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6554 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6555 GLuint shader_id = c.shader;
6556 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6557 Bucket* bucket = CreateBucket(bucket_id);
6558 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6559 if (!shader || !shader->log_info()) {
6560 bucket->SetFromString("");
6561 return error::kNoError;
6563 bucket->SetFromString(shader->log_info()->c_str());
6564 return error::kNoError;
6567 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6568 return state_.GetEnabled(cap);
6571 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6572 const Buffer* buffer = GetBuffer(client_id);
6573 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6576 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6577 const Framebuffer* framebuffer =
6578 GetFramebuffer(client_id);
6579 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6582 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6583 // IsProgram is true for programs as soon as they are created, until they are
6584 // deleted and no longer in use.
6585 const Program* program = GetProgram(client_id);
6586 return program != NULL && !program->IsDeleted();
6589 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6590 const Renderbuffer* renderbuffer =
6591 GetRenderbuffer(client_id);
6592 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6595 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6596 // IsShader is true for shaders as soon as they are created, until they
6597 // are deleted and not attached to any programs.
6598 const Shader* shader = GetShader(client_id);
6599 return shader != NULL && !shader->IsDeleted();
6602 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6603 const TextureRef* texture_ref = GetTexture(client_id);
6604 return texture_ref && texture_ref->texture()->IsValid();
6607 void GLES2DecoderImpl::DoAttachShader(
6608 GLuint program_client_id, GLint shader_client_id) {
6609 Program* program = GetProgramInfoNotShader(
6610 program_client_id, "glAttachShader");
6614 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6618 if (!program->AttachShader(shader_manager(), shader)) {
6620 GL_INVALID_OPERATION,
6622 "can not attach more than one shader of the same type.");
6625 glAttachShader(program->service_id(), shader->service_id());
6628 void GLES2DecoderImpl::DoDetachShader(
6629 GLuint program_client_id, GLint shader_client_id) {
6630 Program* program = GetProgramInfoNotShader(
6631 program_client_id, "glDetachShader");
6635 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6639 if (!program->DetachShader(shader_manager(), shader)) {
6641 GL_INVALID_OPERATION,
6642 "glDetachShader", "shader not attached to program");
6645 glDetachShader(program->service_id(), shader->service_id());
6648 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6649 Program* program = GetProgramInfoNotShader(
6650 program_client_id, "glValidateProgram");
6654 program->Validate();
6657 void GLES2DecoderImpl::GetVertexAttribHelper(
6658 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6660 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6661 Buffer* buffer = attrib->buffer();
6662 if (buffer && !buffer->IsDeleted()) {
6664 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6665 *params = client_id;
6669 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6670 *params = attrib->enabled();
6672 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6673 *params = attrib->size();
6675 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6676 *params = attrib->gl_stride();
6678 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6679 *params = attrib->type();
6681 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6682 *params = attrib->normalized();
6684 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6685 *params = attrib->divisor();
6693 void GLES2DecoderImpl::DoGetVertexAttribfv(
6694 GLuint index, GLenum pname, GLfloat* params) {
6695 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6698 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6702 case GL_CURRENT_VERTEX_ATTRIB: {
6703 const Vec4& value = state_.attrib_values[index];
6704 params[0] = value.v[0];
6705 params[1] = value.v[1];
6706 params[2] = value.v[2];
6707 params[3] = value.v[3];
6712 GetVertexAttribHelper(attrib, pname, &value);
6713 *params = static_cast<GLfloat>(value);
6719 void GLES2DecoderImpl::DoGetVertexAttribiv(
6720 GLuint index, GLenum pname, GLint* params) {
6721 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6724 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6728 case GL_CURRENT_VERTEX_ATTRIB: {
6729 const Vec4& value = state_.attrib_values[index];
6730 params[0] = static_cast<GLint>(value.v[0]);
6731 params[1] = static_cast<GLint>(value.v[1]);
6732 params[2] = static_cast<GLint>(value.v[2]);
6733 params[3] = static_cast<GLint>(value.v[3]);
6737 GetVertexAttribHelper(attrib, pname, params);
6742 bool GLES2DecoderImpl::SetVertexAttribValue(
6743 const char* function_name, GLuint index, const GLfloat* value) {
6744 if (index >= state_.attrib_values.size()) {
6745 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
6748 Vec4& v = state_.attrib_values[index];
6756 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6757 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6758 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6759 glVertexAttrib1f(index, v0);
6763 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
6764 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6765 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6766 glVertexAttrib2f(index, v0, v1);
6770 void GLES2DecoderImpl::DoVertexAttrib3f(
6771 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
6772 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6773 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6774 glVertexAttrib3f(index, v0, v1, v2);
6778 void GLES2DecoderImpl::DoVertexAttrib4f(
6779 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
6780 GLfloat v[4] = { v0, v1, v2, v3, };
6781 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6782 glVertexAttrib4f(index, v0, v1, v2, v3);
6786 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
6787 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6788 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6789 glVertexAttrib1fv(index, v);
6793 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
6794 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6795 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6796 glVertexAttrib2fv(index, v);
6800 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
6801 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6802 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6803 glVertexAttrib3fv(index, v);
6807 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
6808 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6809 glVertexAttrib4fv(index, v);
6813 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
6814 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
6816 if (!state_.bound_array_buffer.get() ||
6817 state_.bound_array_buffer->IsDeleted()) {
6818 if (state_.vertex_attrib_manager.get() ==
6819 default_vertex_attrib_manager_.get()) {
6821 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
6822 return error::kNoError;
6823 } else if (c.offset != 0) {
6826 "glVertexAttribPointer", "client side arrays are not allowed");
6827 return error::kNoError;
6831 GLuint indx = c.indx;
6832 GLint size = c.size;
6833 GLenum type = c.type;
6834 GLboolean normalized = c.normalized;
6835 GLsizei stride = c.stride;
6836 GLsizei offset = c.offset;
6837 const void* ptr = reinterpret_cast<const void*>(offset);
6838 if (!validators_->vertex_attrib_type.IsValid(type)) {
6839 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
6840 return error::kNoError;
6842 if (!validators_->vertex_attrib_size.IsValid(size)) {
6844 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
6845 return error::kNoError;
6847 if (indx >= group_->max_vertex_attribs()) {
6849 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
6850 return error::kNoError;
6854 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
6855 return error::kNoError;
6859 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
6860 return error::kNoError;
6864 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
6865 return error::kNoError;
6867 GLsizei component_size =
6868 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
6869 if (offset % component_size > 0) {
6871 GL_INVALID_OPERATION,
6872 "glVertexAttribPointer", "offset not valid for type");
6873 return error::kNoError;
6875 if (stride % component_size > 0) {
6877 GL_INVALID_OPERATION,
6878 "glVertexAttribPointer", "stride not valid for type");
6879 return error::kNoError;
6881 state_.vertex_attrib_manager
6882 ->SetAttribInfo(indx,
6883 state_.bound_array_buffer.get(),
6888 stride != 0 ? stride : component_size * size,
6890 if (type != GL_FIXED) {
6891 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6893 return error::kNoError;
6896 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6898 state_.viewport_x = x;
6899 state_.viewport_y = y;
6900 state_.viewport_width = std::min(width, viewport_max_width_);
6901 state_.viewport_height = std::min(height, viewport_max_height_);
6902 glViewport(x, y, width, height);
6905 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6906 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
6907 if (!features().angle_instanced_arrays) {
6909 GL_INVALID_OPERATION,
6910 "glVertexAttribDivisorANGLE", "function not available");
6912 GLuint index = c.index;
6913 GLuint divisor = c.divisor;
6914 if (index >= group_->max_vertex_attribs()) {
6917 "glVertexAttribDivisorANGLE", "index out of range");
6918 return error::kNoError;
6921 state_.vertex_attrib_manager->SetDivisor(
6924 glVertexAttribDivisorANGLE(index, divisor);
6925 return error::kNoError;
6928 void GLES2DecoderImpl::FinishReadPixels(
6929 const cmds::ReadPixels& c,
6931 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
6932 GLsizei width = c.width;
6933 GLsizei height = c.height;
6934 GLenum format = c.format;
6935 GLenum type = c.type;
6936 typedef cmds::ReadPixels::Result Result;
6938 Result* result = NULL;
6939 if (c.result_shm_id != 0) {
6940 result = GetSharedMemoryAs<Result*>(
6941 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6944 glDeleteBuffersARB(1, &buffer);
6949 GLES2Util::ComputeImageDataSizes(
6950 width, height, format, type, state_.pack_alignment, &pixels_size,
6952 void* pixels = GetSharedMemoryAs<void*>(
6953 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
6956 glDeleteBuffersARB(1, &buffer);
6962 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
6964 if (features().map_buffer_range) {
6965 data = glMapBufferRange(
6966 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
6968 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
6970 memcpy(pixels, data, pixels_size);
6971 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
6972 // have to restore the state.
6973 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
6974 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
6975 glDeleteBuffersARB(1, &buffer);
6978 if (result != NULL) {
6982 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6983 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6984 if ((channels_exist & 0x0008) == 0 &&
6985 workarounds().clear_alpha_in_readpixels) {
6986 // Set the alpha to 255 because some drivers are buggy in this regard.
6989 uint32 unpadded_row_size;
6990 uint32 padded_row_size;
6991 if (!GLES2Util::ComputeImageDataSizes(
6992 width, 2, format, type, state_.pack_alignment, &temp_size,
6993 &unpadded_row_size, &padded_row_size)) {
6996 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6997 // of this implementation.
6998 if (type != GL_UNSIGNED_BYTE) {
7005 int offset = (format == GL_ALPHA) ? 0 : 3;
7006 int step = (format == GL_ALPHA) ? 1 : 4;
7007 uint8* dst = static_cast<uint8*>(pixels) + offset;
7008 for (GLint yy = 0; yy < height; ++yy) {
7009 uint8* end = dst + unpadded_row_size;
7010 for (uint8* d = dst; d < end; d += step) {
7013 dst += padded_row_size;
7024 error::Error GLES2DecoderImpl::HandleReadPixels(
7025 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7026 if (ShouldDeferReads())
7027 return error::kDeferCommandUntilLater;
7030 GLsizei width = c.width;
7031 GLsizei height = c.height;
7032 GLenum format = c.format;
7033 GLenum type = c.type;
7034 GLboolean async = c.async;
7035 if (width < 0 || height < 0) {
7036 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7037 return error::kNoError;
7039 typedef cmds::ReadPixels::Result Result;
7041 if (!GLES2Util::ComputeImageDataSizes(
7042 width, height, format, type, state_.pack_alignment, &pixels_size,
7044 return error::kOutOfBounds;
7046 void* pixels = GetSharedMemoryAs<void*>(
7047 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7049 return error::kOutOfBounds;
7051 Result* result = NULL;
7052 if (c.result_shm_id != 0) {
7053 result = GetSharedMemoryAs<Result*>(
7054 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7056 return error::kOutOfBounds;
7060 if (!validators_->read_pixel_format.IsValid(format)) {
7061 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7062 return error::kNoError;
7064 if (!validators_->pixel_type.IsValid(type)) {
7065 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7066 return error::kNoError;
7068 if (width == 0 || height == 0) {
7069 return error::kNoError;
7072 // Get the size of the current fbo or backbuffer.
7073 gfx::Size max_size = GetBoundReadFrameBufferSize();
7077 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7079 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7080 return error::kNoError;
7083 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7084 return error::kNoError;
7087 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
7089 ScopedResolvedFrameBufferBinder binder(this, false, true);
7091 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7092 // The user requested an out of range area. Get the results 1 line
7095 uint32 unpadded_row_size;
7096 uint32 padded_row_size;
7097 if (!GLES2Util::ComputeImageDataSizes(
7098 width, 2, format, type, state_.pack_alignment, &temp_size,
7099 &unpadded_row_size, &padded_row_size)) {
7101 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7102 return error::kNoError;
7105 GLint dest_x_offset = std::max(-x, 0);
7106 uint32 dest_row_offset;
7107 if (!GLES2Util::ComputeImageDataSizes(
7108 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7111 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7112 return error::kNoError;
7115 // Copy each row into the larger dest rect.
7116 int8* dst = static_cast<int8*>(pixels);
7117 GLint read_x = std::max(0, x);
7118 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7119 GLint read_width = read_end_x - read_x;
7120 for (GLint yy = 0; yy < height; ++yy) {
7124 memset(dst, 0, unpadded_row_size);
7126 // If the row is in range, copy it.
7127 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7129 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7131 dst += padded_row_size;
7134 if (async && features().use_async_readpixels) {
7136 glGenBuffersARB(1, &buffer);
7137 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7138 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7139 GLenum error = glGetError();
7140 if (error == GL_NO_ERROR) {
7141 glReadPixels(x, y, width, height, format, type, 0);
7142 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7143 new FenceCallback()));
7144 WaitForReadPixels(base::Bind(
7145 &GLES2DecoderImpl::FinishReadPixels,
7146 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7147 <GLES2DecoderImpl>(this),
7149 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7150 return error::kNoError;
7153 glReadPixels(x, y, width, height, format, type, pixels);
7155 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7156 if (error == GL_NO_ERROR) {
7157 if (result != NULL) {
7160 FinishReadPixels(c, 0);
7163 return error::kNoError;
7166 error::Error GLES2DecoderImpl::HandlePixelStorei(
7167 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7168 GLenum pname = c.pname;
7169 GLenum param = c.param;
7170 if (!validators_->pixel_store.IsValid(pname)) {
7171 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7172 return error::kNoError;
7175 case GL_PACK_ALIGNMENT:
7176 case GL_UNPACK_ALIGNMENT:
7177 if (!validators_->pixel_store_alignment.IsValid(param)) {
7179 GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
7180 return error::kNoError;
7183 case GL_UNPACK_FLIP_Y_CHROMIUM:
7184 unpack_flip_y_ = (param != 0);
7185 return error::kNoError;
7186 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7187 unpack_premultiply_alpha_ = (param != 0);
7188 return error::kNoError;
7189 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7190 unpack_unpremultiply_alpha_ = (param != 0);
7191 return error::kNoError;
7195 glPixelStorei(pname, param);
7197 case GL_PACK_ALIGNMENT:
7198 state_.pack_alignment = param;
7200 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7201 state_.pack_reverse_row_order = (param != 0);
7203 case GL_UNPACK_ALIGNMENT:
7204 state_.unpack_alignment = param;
7207 // Validation should have prevented us from getting here.
7211 return error::kNoError;
7214 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7215 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7216 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7217 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
7219 GL_INVALID_OPERATION,
7220 "glPostSubBufferCHROMIUM", "command not supported by surface");
7221 return error::kNoError;
7224 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7227 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7228 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7229 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7230 is_offscreen ? offscreen_size_ : surface_->GetSize());
7232 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7233 return error::kNoError;
7235 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7236 return error::kLostContext;
7240 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7241 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7242 const std::string& name_str) {
7243 if (!StringIsValidForGLES(name_str.c_str())) {
7245 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7246 return error::kNoError;
7248 Program* program = GetProgramInfoNotShader(
7249 client_id, "glGetAttribLocation");
7251 return error::kNoError;
7253 if (!program->IsValid()) {
7255 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7256 return error::kNoError;
7258 GLint* location = GetSharedMemoryAs<GLint*>(
7259 location_shm_id, location_shm_offset, sizeof(GLint));
7261 return error::kOutOfBounds;
7263 // Require the client to init this incase the context is lost and we are no
7264 // longer executing commands.
7265 if (*location != -1) {
7266 return error::kGenericError;
7268 *location = program->GetAttribLocation(name_str);
7269 return error::kNoError;
7272 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7273 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7274 uint32 name_size = c.data_size;
7275 const char* name = GetSharedMemoryAs<const char*>(
7276 c.name_shm_id, c.name_shm_offset, name_size);
7278 return error::kOutOfBounds;
7280 String name_str(name, name_size);
7281 return GetAttribLocationHelper(
7282 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7285 error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
7286 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
7287 Bucket* bucket = GetBucket(c.name_bucket_id);
7289 return error::kInvalidArguments;
7291 std::string name_str;
7292 if (!bucket->GetAsString(&name_str)) {
7293 return error::kInvalidArguments;
7295 return GetAttribLocationHelper(
7296 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7299 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7300 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7301 const std::string& name_str) {
7302 if (!StringIsValidForGLES(name_str.c_str())) {
7304 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7305 return error::kNoError;
7307 Program* program = GetProgramInfoNotShader(
7308 client_id, "glUniformLocation");
7310 return error::kNoError;
7312 if (!program->IsValid()) {
7314 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7315 return error::kNoError;
7317 GLint* location = GetSharedMemoryAs<GLint*>(
7318 location_shm_id, location_shm_offset, sizeof(GLint));
7320 return error::kOutOfBounds;
7322 // Require the client to init this incase the context is lost an we are no
7323 // longer executing commands.
7324 if (*location != -1) {
7325 return error::kGenericError;
7327 *location = program->GetUniformFakeLocation(name_str);
7328 return error::kNoError;
7331 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7332 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7333 uint32 name_size = c.data_size;
7334 const char* name = GetSharedMemoryAs<const char*>(
7335 c.name_shm_id, c.name_shm_offset, name_size);
7337 return error::kOutOfBounds;
7339 String name_str(name, name_size);
7340 return GetUniformLocationHelper(
7341 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7344 error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
7345 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
7346 Bucket* bucket = GetBucket(c.name_bucket_id);
7348 return error::kInvalidArguments;
7350 std::string name_str;
7351 if (!bucket->GetAsString(&name_str)) {
7352 return error::kInvalidArguments;
7354 return GetUniformLocationHelper(
7355 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7358 error::Error GLES2DecoderImpl::HandleGetString(
7359 uint32 immediate_data_size, const cmds::GetString& c) {
7360 GLenum name = static_cast<GLenum>(c.name);
7361 if (!validators_->string_type.IsValid(name)) {
7362 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7363 return error::kNoError;
7365 const char* str = reinterpret_cast<const char*>(glGetString(name));
7366 std::string extensions;
7369 str = "OpenGL ES 2.0 Chromium";
7371 case GL_SHADING_LANGUAGE_VERSION:
7372 str = "OpenGL ES GLSL ES 1.0 Chromium";
7376 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7377 // They are used by WEBGL_debug_renderer_info.
7378 if (!force_webgl_glsl_validation_)
7383 // For WebGL contexts, strip out the OES derivatives and
7384 // EXT frag depth extensions if they have not been enabled.
7385 if (force_webgl_glsl_validation_) {
7386 extensions = feature_info_->extensions();
7387 if (!derivatives_explicitly_enabled_) {
7388 size_t offset = extensions.find(kOESDerivativeExtension);
7389 if (std::string::npos != offset) {
7390 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7394 if (!frag_depth_explicitly_enabled_) {
7395 size_t offset = extensions.find(kEXTFragDepthExtension);
7396 if (std::string::npos != offset) {
7397 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7401 if (!draw_buffers_explicitly_enabled_) {
7402 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7403 if (std::string::npos != offset) {
7404 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7409 extensions = feature_info_->extensions().c_str();
7411 std::string surface_extensions = surface_->GetExtensions();
7412 if (!surface_extensions.empty())
7413 extensions += " " + surface_extensions;
7414 str = extensions.c_str();
7420 Bucket* bucket = CreateBucket(c.bucket_id);
7421 bucket->SetFromString(str);
7422 return error::kNoError;
7425 error::Error GLES2DecoderImpl::HandleBufferData(
7426 uint32 immediate_data_size, const cmds::BufferData& c) {
7427 GLenum target = static_cast<GLenum>(c.target);
7428 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7429 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7430 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7431 GLenum usage = static_cast<GLenum>(c.usage);
7432 const void* data = NULL;
7433 if (data_shm_id != 0 || data_shm_offset != 0) {
7434 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7436 return error::kOutOfBounds;
7439 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7440 return error::kNoError;
7443 void GLES2DecoderImpl::DoBufferSubData(
7444 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7445 // Just delegate it. Some validation is actually done before this.
7446 buffer_manager()->ValidateAndDoBufferSubData(
7447 &state_, target, offset, size, data);
7450 bool GLES2DecoderImpl::ClearLevel(
7451 unsigned service_id,
7452 unsigned bind_target,
7459 bool is_texture_immutable) {
7460 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7461 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
7462 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7463 // on depth formats.
7465 glGenFramebuffersEXT(1, &fb);
7466 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7468 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7469 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7470 GL_DEPTH_ATTACHMENT;
7472 glFramebufferTexture2DEXT(
7473 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7474 // ANGLE promises a depth only attachment ok.
7475 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7476 GL_FRAMEBUFFER_COMPLETE) {
7483 glDisable(GL_SCISSOR_TEST);
7484 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7486 RestoreClearState();
7488 glDeleteFramebuffersEXT(1, &fb);
7489 Framebuffer* framebuffer =
7490 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7491 GLuint fb_service_id =
7492 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7493 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7497 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7500 uint32 padded_row_size;
7501 if (!GLES2Util::ComputeImageDataSizes(
7502 width, height, format, type, state_.unpack_alignment, &size,
7503 NULL, &padded_row_size)) {
7507 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7511 if (size > kMaxZeroSize) {
7512 if (kMaxZeroSize < padded_row_size) {
7513 // That'd be an awfully large texture.
7516 // We should never have a large total size with a zero row size.
7517 DCHECK_GT(padded_row_size, 0U);
7518 tile_height = kMaxZeroSize / padded_row_size;
7519 if (!GLES2Util::ComputeImageDataSizes(
7520 width, tile_height, format, type, state_.unpack_alignment, &size,
7525 tile_height = height;
7528 // Assumes the size has already been checked.
7529 scoped_ptr<char[]> zero(new char[size]);
7530 memset(zero.get(), 0, size);
7531 glBindTexture(bind_target, service_id);
7534 while (y < height) {
7535 GLint h = y + tile_height > height ? height - y : tile_height;
7536 if (is_texture_immutable || h != height) {
7537 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7540 target, level, format, width, h, 0, format, type, zero.get());
7544 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7545 &state_, bind_target);
7546 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7552 const int kS3TCBlockWidth = 4;
7553 const int kS3TCBlockHeight = 4;
7554 const int kS3TCDXT1BlockSize = 8;
7555 const int kS3TCDXT3AndDXT5BlockSize = 16;
7556 const int kETC1BlockWidth = 4;
7557 const int kETC1BlockHeight = 4;
7558 const int kETC1BlockSize = 8;
7560 bool IsValidDXTSize(GLint level, GLsizei size) {
7561 return (size == 1) ||
7562 (size == 2) || !(size % kS3TCBlockWidth);
7565 } // anonymous namespace.
7567 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7568 const char* function_name,
7569 GLsizei width, GLsizei height, GLenum format, size_t size) {
7570 unsigned int bytes_required = 0;
7573 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7574 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7575 int num_blocks_across =
7576 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7577 int num_blocks_down =
7578 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7579 int num_blocks = num_blocks_across * num_blocks_down;
7580 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7583 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7584 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7585 int num_blocks_across =
7586 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7587 int num_blocks_down =
7588 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7589 int num_blocks = num_blocks_across * num_blocks_down;
7590 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7593 case GL_ETC1_RGB8_OES: {
7594 int num_blocks_across =
7595 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7596 int num_blocks_down =
7597 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7598 int num_blocks = num_blocks_across * num_blocks_down;
7599 bytes_required = num_blocks * kETC1BlockSize;
7603 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7607 if (size != bytes_required) {
7609 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7616 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7617 const char* function_name,
7618 GLint level, GLsizei width, GLsizei height, GLenum format) {
7620 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7621 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7622 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7623 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7624 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7626 GL_INVALID_OPERATION, function_name,
7627 "width or height invalid for level");
7632 case GL_ETC1_RGB8_OES:
7633 if (width <= 0 || height <= 0) {
7635 GL_INVALID_OPERATION, function_name,
7636 "width or height invalid for level");
7645 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7646 const char* function_name,
7647 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7648 GLsizei width, GLsizei height, GLenum format,
7650 if (xoffset < 0 || yoffset < 0) {
7652 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7657 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7658 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7659 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7660 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7661 const int kBlockWidth = 4;
7662 const int kBlockHeight = 4;
7663 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7665 GL_INVALID_OPERATION, function_name,
7666 "xoffset or yoffset not multiple of 4");
7669 GLsizei tex_width = 0;
7670 GLsizei tex_height = 0;
7671 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7672 width - xoffset > tex_width ||
7673 height - yoffset > tex_height) {
7675 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7678 return ValidateCompressedTexDimensions(
7679 function_name, level, width, height, format);
7681 case GL_ETC1_RGB8_OES: {
7683 GL_INVALID_OPERATION, function_name,
7684 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7692 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7695 GLenum internal_format,
7701 // TODO(gman): Validate image_size is correct for width, height and format.
7702 if (!validators_->texture_target.IsValid(target)) {
7703 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7704 "glCompressedTexImage2D", target, "target");
7705 return error::kNoError;
7707 if (!validators_->compressed_texture_format.IsValid(
7709 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7710 "glCompressedTexImage2D", internal_format, "internal_format");
7711 return error::kNoError;
7713 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7717 "glCompressedTexImage2D", "dimensions out of range");
7718 return error::kNoError;
7720 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7725 "glCompressedTexImage2D", "unknown texture target");
7726 return error::kNoError;
7728 Texture* texture = texture_ref->texture();
7729 if (texture->IsImmutable()) {
7731 GL_INVALID_OPERATION,
7732 "glCompressedTexImage2D", "texture is immutable");
7733 return error::kNoError;
7736 if (!ValidateCompressedTexDimensions(
7737 "glCompressedTexImage2D", level, width, height, internal_format) ||
7738 !ValidateCompressedTexFuncData(
7739 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
7740 return error::kNoError;
7743 if (!EnsureGPUMemoryAvailable(image_size)) {
7745 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
7746 return error::kNoError;
7749 if (texture->IsAttachedToFramebuffer()) {
7750 framebuffer_state_.clear_state_dirty = true;
7753 scoped_ptr<int8[]> zero;
7755 zero.reset(new int8[image_size]);
7756 memset(zero.get(), 0, image_size);
7759 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
7760 glCompressedTexImage2D(
7761 target, level, internal_format, width, height, border, image_size, data);
7762 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
7763 if (error == GL_NO_ERROR) {
7764 texture_manager()->SetLevelInfo(
7765 texture_ref, target, level, internal_format,
7766 width, height, 1, border, 0, 0, true);
7768 return error::kNoError;
7771 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
7772 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
7773 GLenum target = static_cast<GLenum>(c.target);
7774 GLint level = static_cast<GLint>(c.level);
7775 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7776 GLsizei width = static_cast<GLsizei>(c.width);
7777 GLsizei height = static_cast<GLsizei>(c.height);
7778 GLint border = static_cast<GLint>(c.border);
7779 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7780 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7781 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7782 const void* data = NULL;
7783 if (data_shm_id != 0 || data_shm_offset != 0) {
7784 data = GetSharedMemoryAs<const void*>(
7785 data_shm_id, data_shm_offset, image_size);
7787 return error::kOutOfBounds;
7790 return DoCompressedTexImage2D(
7791 target, level, internal_format, width, height, border, image_size, data);
7794 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
7795 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
7796 GLenum target = static_cast<GLenum>(c.target);
7797 GLint level = static_cast<GLint>(c.level);
7798 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7799 GLsizei width = static_cast<GLsizei>(c.width);
7800 GLsizei height = static_cast<GLsizei>(c.height);
7801 GLint border = static_cast<GLint>(c.border);
7802 Bucket* bucket = GetBucket(c.bucket_id);
7804 return error::kInvalidArguments;
7806 uint32 data_size = bucket->size();
7807 GLsizei imageSize = data_size;
7808 const void* data = bucket->GetData(0, data_size);
7810 return error::kInvalidArguments;
7812 return DoCompressedTexImage2D(
7813 target, level, internal_format, width, height, border,
7817 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7818 uint32 immediate_data_size,
7819 const cmds::CompressedTexSubImage2DBucket& c) {
7820 GLenum target = static_cast<GLenum>(c.target);
7821 GLint level = static_cast<GLint>(c.level);
7822 GLint xoffset = static_cast<GLint>(c.xoffset);
7823 GLint yoffset = static_cast<GLint>(c.yoffset);
7824 GLsizei width = static_cast<GLsizei>(c.width);
7825 GLsizei height = static_cast<GLsizei>(c.height);
7826 GLenum format = static_cast<GLenum>(c.format);
7827 Bucket* bucket = GetBucket(c.bucket_id);
7829 return error::kInvalidArguments;
7831 uint32 data_size = bucket->size();
7832 GLsizei imageSize = data_size;
7833 const void* data = bucket->GetData(0, data_size);
7835 return error::kInvalidArguments;
7837 if (!validators_->texture_target.IsValid(target)) {
7839 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
7840 return error::kNoError;
7842 if (!validators_->compressed_texture_format.IsValid(format)) {
7843 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7844 "glCompressedTexSubImage2D", format, "format");
7845 return error::kNoError;
7849 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
7850 return error::kNoError;
7854 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
7855 return error::kNoError;
7857 if (imageSize < 0) {
7859 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
7860 return error::kNoError;
7862 DoCompressedTexSubImage2D(
7863 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7864 return error::kNoError;
7867 error::Error GLES2DecoderImpl::HandleTexImage2D(
7868 uint32 immediate_data_size, const cmds::TexImage2D& c) {
7869 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
7870 // Set as failed for now, but if it successed, this will be set to not failed.
7871 texture_state_.tex_image_2d_failed = true;
7872 GLenum target = static_cast<GLenum>(c.target);
7873 GLint level = static_cast<GLint>(c.level);
7874 // TODO(kloveless): Change TexImage2D command to use unsigned integer
7875 // for internalformat.
7876 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7877 GLsizei width = static_cast<GLsizei>(c.width);
7878 GLsizei height = static_cast<GLsizei>(c.height);
7879 GLint border = static_cast<GLint>(c.border);
7880 GLenum format = static_cast<GLenum>(c.format);
7881 GLenum type = static_cast<GLenum>(c.type);
7882 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7883 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
7885 if (!GLES2Util::ComputeImageDataSizes(
7886 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
7888 return error::kOutOfBounds;
7890 const void* pixels = NULL;
7891 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7892 pixels = GetSharedMemoryAs<const void*>(
7893 pixels_shm_id, pixels_shm_offset, pixels_size);
7895 return error::kOutOfBounds;
7899 TextureManager::DoTextImage2DArguments args = {
7900 target, level, internal_format, width, height, border, format, type,
7901 pixels, pixels_size};
7902 texture_manager()->ValidateAndDoTexImage2D(
7903 &texture_state_, &state_, &framebuffer_state_, args);
7904 return error::kNoError;
7907 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7916 const void * data) {
7917 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7921 GL_INVALID_OPERATION,
7922 "glCompressedTexSubImage2D", "unknown texture for target");
7925 Texture* texture = texture_ref->texture();
7927 GLenum internal_format = 0;
7928 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
7930 GL_INVALID_OPERATION,
7931 "glCompressedTexSubImage2D", "level does not exist.");
7934 if (internal_format != format) {
7936 GL_INVALID_OPERATION,
7937 "glCompressedTexSubImage2D", "format does not match internal format.");
7940 if (!texture->ValidForTexture(
7941 target, level, xoffset, yoffset, width, height, format, type)) {
7943 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
7947 if (!ValidateCompressedTexFuncData(
7948 "glCompressedTexSubImage2D", width, height, format, image_size) ||
7949 !ValidateCompressedTexSubDimensions(
7950 "glCompressedTexSubImage2D",
7951 target, level, xoffset, yoffset, width, height, format, texture)) {
7956 // Note: There is no need to deal with texture cleared tracking here
7957 // because the validation above means you can only get here if the level
7958 // is already a matching compressed format and in that case
7959 // CompressedTexImage2D already cleared the texture.
7960 glCompressedTexSubImage2D(
7961 target, level, xoffset, yoffset, width, height, format, image_size, data);
7965 GLint start, GLint range, GLint sourceRange,
7966 GLint* out_start, GLint* out_range) {
7973 GLint end = start + range;
7974 if (end > sourceRange) {
7975 range -= end - sourceRange;
7981 void GLES2DecoderImpl::DoCopyTexImage2D(
7984 GLenum internal_format,
7990 DCHECK(!ShouldDeferReads());
7991 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7995 GL_INVALID_OPERATION,
7996 "glCopyTexImage2D", "unknown texture for target");
7999 Texture* texture = texture_ref->texture();
8000 if (texture->IsImmutable()) {
8002 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8004 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8007 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8010 if (!texture_manager()->ValidateTextureParameters(
8011 state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
8012 GL_UNSIGNED_BYTE, level)) {
8016 // Check we have compatible formats.
8017 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8018 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8019 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8021 if ((channels_needed & channels_exist) != channels_needed) {
8023 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8027 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8029 GL_INVALID_OPERATION,
8030 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8034 uint32 estimated_size = 0;
8035 if (!GLES2Util::ComputeImageDataSizes(
8036 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8037 &estimated_size, NULL, NULL)) {
8039 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8043 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8044 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8048 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8052 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8053 ScopedResolvedFrameBufferBinder binder(this, false, true);
8054 gfx::Size size = GetBoundReadFrameBufferSize();
8056 if (texture->IsAttachedToFramebuffer()) {
8057 framebuffer_state_.clear_state_dirty = true;
8060 // Clip to size to source dimensions
8063 GLint copyWidth = 0;
8064 GLint copyHeight = 0;
8065 Clip(x, width, size.width(), ©X, ©Width);
8066 Clip(y, height, size.height(), ©Y, ©Height);
8070 copyWidth != width ||
8071 copyHeight != height) {
8072 // some part was clipped so clear the texture.
8074 texture->service_id(), texture->target(),
8075 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
8076 texture->IsImmutable())) {
8078 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8081 if (copyHeight > 0 && copyWidth > 0) {
8082 GLint dx = copyX - x;
8083 GLint dy = copyY - y;
8086 glCopyTexSubImage2D(target, level,
8087 destX, destY, copyX, copyY,
8088 copyWidth, copyHeight);
8091 glCopyTexImage2D(target, level, internal_format,
8092 copyX, copyY, copyWidth, copyHeight, border);
8094 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8095 if (error == GL_NO_ERROR) {
8096 texture_manager()->SetLevelInfo(
8097 texture_ref, target, level, internal_format, width, height, 1,
8098 border, internal_format, GL_UNSIGNED_BYTE, true);
8102 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8111 DCHECK(!ShouldDeferReads());
8112 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8116 GL_INVALID_OPERATION,
8117 "glCopyTexSubImage2D", "unknown texture for target");
8120 Texture* texture = texture_ref->texture();
8123 if (!texture->GetLevelType(target, level, &type, &format) ||
8124 !texture->ValidForTexture(
8125 target, level, xoffset, yoffset, width, height, format, type)) {
8127 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8130 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8132 GL_INVALID_OPERATION,
8133 "glCopyTexSubImage2D", "async upload pending for texture");
8137 // Check we have compatible formats.
8138 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8139 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8140 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8142 if (!channels_needed ||
8143 (channels_needed & channels_exist) != channels_needed) {
8145 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8149 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8151 GL_INVALID_OPERATION,
8152 "glCopySubImage2D", "can not be used with depth or stencil textures");
8156 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8160 ScopedResolvedFrameBufferBinder binder(this, false, true);
8161 gfx::Size size = GetBoundReadFrameBufferSize();
8164 GLint copyWidth = 0;
8165 GLint copyHeight = 0;
8166 Clip(x, width, size.width(), ©X, ©Width);
8167 Clip(y, height, size.height(), ©Y, ©Height);
8169 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8171 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8177 copyWidth != width ||
8178 copyHeight != height) {
8179 // some part was clipped so clear the sub rect.
8180 uint32 pixels_size = 0;
8181 if (!GLES2Util::ComputeImageDataSizes(
8182 width, height, format, type, state_.unpack_alignment, &pixels_size,
8185 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8188 scoped_ptr<char[]> zero(new char[pixels_size]);
8189 memset(zero.get(), 0, pixels_size);
8191 target, level, xoffset, yoffset, width, height,
8192 format, type, zero.get());
8195 if (copyHeight > 0 && copyWidth > 0) {
8196 GLint dx = copyX - x;
8197 GLint dy = copyY - y;
8198 GLint destX = xoffset + dx;
8199 GLint destY = yoffset + dy;
8200 glCopyTexSubImage2D(target, level,
8201 destX, destY, copyX, copyY,
8202 copyWidth, copyHeight);
8206 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8207 error::Error* error,
8208 const char* function_name,
8217 const void * data) {
8218 (*error) = error::kNoError;
8219 if (!validators_->texture_target.IsValid(target)) {
8220 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8228 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8231 if (!validators_->texture_format.IsValid(format)) {
8232 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8235 if (!validators_->pixel_type.IsValid(type)) {
8236 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
8239 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8243 GL_INVALID_OPERATION,
8244 function_name, "unknown texture for target");
8247 Texture* texture = texture_ref->texture();
8248 GLenum current_type = 0;
8249 GLenum internal_format = 0;
8250 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) {
8252 GL_INVALID_OPERATION, function_name, "level does not exist.");
8255 if (format != internal_format) {
8257 GL_INVALID_OPERATION,
8258 function_name, "format does not match internal format.");
8261 if (type != current_type) {
8263 GL_INVALID_OPERATION,
8264 function_name, "type does not match type of texture.");
8267 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8269 GL_INVALID_OPERATION,
8270 function_name, "async upload pending for texture");
8273 if (!texture->ValidForTexture(
8274 target, level, xoffset, yoffset, width, height, format, type)) {
8275 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8278 if ((GLES2Util::GetChannelsForFormat(format) &
8279 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8281 GL_INVALID_OPERATION,
8282 function_name, "can not supply data for depth or stencil textures");
8286 (*error) = error::kOutOfBounds;
8292 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8301 const void * data) {
8302 error::Error error = error::kNoError;
8303 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8304 xoffset, yoffset, width, height, format, type, data)) {
8307 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8309 Texture* texture = texture_ref->texture();
8310 GLsizei tex_width = 0;
8311 GLsizei tex_height = 0;
8312 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8314 if (xoffset != 0 || yoffset != 0 ||
8315 width != tex_width || height != tex_height) {
8316 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8319 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8320 return error::kNoError;
8322 ScopedTextureUploadTimer timer(&texture_state_);
8324 target, level, xoffset, yoffset, width, height, format, type, data);
8325 return error::kNoError;
8328 if (texture_state_.teximage2d_faster_than_texsubimage2d &&
8329 !texture->IsImmutable()) {
8330 ScopedTextureUploadTimer timer(&texture_state_);
8331 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8332 // same as internal_foramt. If that changes we'll need to look them up.
8334 target, level, format, width, height, 0, format, type, data);
8336 ScopedTextureUploadTimer timer(&texture_state_);
8338 target, level, xoffset, yoffset, width, height, format, type, data);
8340 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8341 return error::kNoError;
8344 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8345 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8346 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8347 GLboolean internal = static_cast<GLboolean>(c.internal);
8348 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8349 return error::kNoError;
8351 GLenum target = static_cast<GLenum>(c.target);
8352 GLint level = static_cast<GLint>(c.level);
8353 GLint xoffset = static_cast<GLint>(c.xoffset);
8354 GLint yoffset = static_cast<GLint>(c.yoffset);
8355 GLsizei width = static_cast<GLsizei>(c.width);
8356 GLsizei height = static_cast<GLsizei>(c.height);
8357 GLenum format = static_cast<GLenum>(c.format);
8358 GLenum type = static_cast<GLenum>(c.type);
8360 if (!GLES2Util::ComputeImageDataSizes(
8361 width, height, format, type, state_.unpack_alignment, &data_size,
8363 return error::kOutOfBounds;
8365 const void* pixels = GetSharedMemoryAs<const void*>(
8366 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8367 return DoTexSubImage2D(
8368 target, level, xoffset, yoffset, width, height, format, type, pixels);
8371 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8372 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8373 GLuint index = static_cast<GLuint>(c.index);
8374 GLenum pname = static_cast<GLenum>(c.pname);
8375 typedef cmds::GetVertexAttribPointerv::Result Result;
8376 Result* result = GetSharedMemoryAs<Result*>(
8377 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8379 return error::kOutOfBounds;
8381 // Check that the client initialized the result.
8382 if (result->size != 0) {
8383 return error::kInvalidArguments;
8385 if (!validators_->vertex_pointer.IsValid(pname)) {
8386 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8387 "glGetVertexAttribPointerv", pname, "pname");
8388 return error::kNoError;
8390 if (index >= group_->max_vertex_attribs()) {
8392 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8393 return error::kNoError;
8395 result->SetNumResults(1);
8396 *result->GetData() =
8397 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8398 return error::kNoError;
8401 bool GLES2DecoderImpl::GetUniformSetup(
8402 GLuint program_id, GLint fake_location,
8403 uint32 shm_id, uint32 shm_offset,
8404 error::Error* error, GLint* real_location,
8405 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8408 DCHECK(result_pointer);
8409 DCHECK(result_type);
8410 DCHECK(real_location);
8411 *error = error::kNoError;
8412 // Make sure we have enough room for the result on failure.
8413 SizedResult<GLint>* result;
8414 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8415 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8417 *error = error::kOutOfBounds;
8420 *result_pointer = result;
8421 // Set the result size to 0 so the client does not have to check for success.
8422 result->SetNumResults(0);
8423 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8427 if (!program->IsValid()) {
8428 // Program was not linked successfully. (ie, glLinkProgram)
8430 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8433 *service_id = program->service_id();
8434 GLint array_index = -1;
8435 const Program::UniformInfo* uniform_info =
8436 program->GetUniformInfoByFakeLocation(
8437 fake_location, real_location, &array_index);
8438 if (!uniform_info) {
8439 // No such location.
8441 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8444 GLenum type = uniform_info->type;
8445 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8447 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8450 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8451 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8453 *error = error::kOutOfBounds;
8456 result->size = size;
8457 *result_type = type;
8461 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8462 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8463 GLuint program = c.program;
8464 GLint fake_location = c.location;
8467 GLint real_location = -1;
8470 if (GetUniformSetup(
8471 program, fake_location, c.params_shm_id, c.params_shm_offset,
8472 &error, &real_location, &service_id, &result, &result_type)) {
8474 service_id, real_location,
8475 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8480 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8481 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8482 GLuint program = c.program;
8483 GLint fake_location = c.location;
8485 GLint real_location = -1;
8487 typedef cmds::GetUniformfv::Result Result;
8490 if (GetUniformSetup(
8491 program, fake_location, c.params_shm_id, c.params_shm_offset,
8492 &error, &real_location, &service_id,
8493 reinterpret_cast<void**>(&result), &result_type)) {
8494 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8495 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8496 GLsizei num_values = result->GetNumResults();
8497 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8498 glGetUniformiv(service_id, real_location, temp.get());
8499 GLfloat* dst = result->GetData();
8500 for (GLsizei ii = 0; ii < num_values; ++ii) {
8501 dst[ii] = (temp[ii] != 0);
8504 glGetUniformfv(service_id, real_location, result->GetData());
8510 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8511 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8512 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8513 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8514 typedef cmds::GetShaderPrecisionFormat::Result Result;
8515 Result* result = GetSharedMemoryAs<Result*>(
8516 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8518 return error::kOutOfBounds;
8520 // Check that the client initialized the result.
8521 if (result->success != 0) {
8522 return error::kInvalidArguments;
8524 if (!validators_->shader_type.IsValid(shader_type)) {
8525 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8526 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8527 return error::kNoError;
8529 if (!validators_->shader_precision.IsValid(precision_type)) {
8530 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8531 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8532 return error::kNoError;
8535 result->success = 1; // true
8537 GLint range[2] = { 0, 0 };
8538 GLint precision = 0;
8539 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8541 result->min_range = range[0];
8542 result->max_range = range[1];
8543 result->precision = precision;
8545 return error::kNoError;
8548 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8549 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8550 uint32 result_size = c.result_size;
8551 GLuint program_id = static_cast<GLuint>(c.program);
8552 Program* program = GetProgramInfoNotShader(
8553 program_id, "glGetAttachedShaders");
8555 return error::kNoError;
8557 typedef cmds::GetAttachedShaders::Result Result;
8558 uint32 max_count = Result::ComputeMaxResults(result_size);
8559 Result* result = GetSharedMemoryAs<Result*>(
8560 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8562 return error::kOutOfBounds;
8564 // Check that the client initialized the result.
8565 if (result->size != 0) {
8566 return error::kInvalidArguments;
8569 glGetAttachedShaders(
8570 program->service_id(), max_count, &count, result->GetData());
8571 for (GLsizei ii = 0; ii < count; ++ii) {
8572 if (!shader_manager()->GetClientId(result->GetData()[ii],
8573 &result->GetData()[ii])) {
8575 return error::kGenericError;
8578 result->SetNumResults(count);
8579 return error::kNoError;
8582 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8583 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8584 GLuint program_id = c.program;
8585 GLuint index = c.index;
8586 uint32 name_bucket_id = c.name_bucket_id;
8587 typedef cmds::GetActiveUniform::Result Result;
8588 Result* result = GetSharedMemoryAs<Result*>(
8589 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8591 return error::kOutOfBounds;
8593 // Check that the client initialized the result.
8594 if (result->success != 0) {
8595 return error::kInvalidArguments;
8597 Program* program = GetProgramInfoNotShader(
8598 program_id, "glGetActiveUniform");
8600 return error::kNoError;
8602 const Program::UniformInfo* uniform_info =
8603 program->GetUniformInfo(index);
8604 if (!uniform_info) {
8606 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8607 return error::kNoError;
8609 result->success = 1; // true.
8610 result->size = uniform_info->size;
8611 result->type = uniform_info->type;
8612 Bucket* bucket = CreateBucket(name_bucket_id);
8613 bucket->SetFromString(uniform_info->name.c_str());
8614 return error::kNoError;
8617 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
8618 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8619 GLuint program_id = c.program;
8620 GLuint index = c.index;
8621 uint32 name_bucket_id = c.name_bucket_id;
8622 typedef cmds::GetActiveAttrib::Result Result;
8623 Result* result = GetSharedMemoryAs<Result*>(
8624 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8626 return error::kOutOfBounds;
8628 // Check that the client initialized the result.
8629 if (result->success != 0) {
8630 return error::kInvalidArguments;
8632 Program* program = GetProgramInfoNotShader(
8633 program_id, "glGetActiveAttrib");
8635 return error::kNoError;
8637 const Program::VertexAttrib* attrib_info =
8638 program->GetAttribInfo(index);
8641 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
8642 return error::kNoError;
8644 result->success = 1; // true.
8645 result->size = attrib_info->size;
8646 result->type = attrib_info->type;
8647 Bucket* bucket = CreateBucket(name_bucket_id);
8648 bucket->SetFromString(attrib_info->name.c_str());
8649 return error::kNoError;
8652 error::Error GLES2DecoderImpl::HandleShaderBinary(
8653 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
8654 #if 1 // No binary shader support.
8655 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
8656 return error::kNoError;
8658 GLsizei n = static_cast<GLsizei>(c.n);
8660 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
8661 return error::kNoError;
8663 GLsizei length = static_cast<GLsizei>(c.length);
8665 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
8666 return error::kNoError;
8669 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8670 return error::kOutOfBounds;
8672 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8673 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8674 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8675 const void* binary = GetSharedMemoryAs<const void*>(
8676 c.binary_shm_id, c.binary_shm_offset, length);
8677 if (shaders == NULL || binary == NULL) {
8678 return error::kOutOfBounds;
8680 scoped_array<GLuint> service_ids(new GLuint[n]);
8681 for (GLsizei ii = 0; ii < n; ++ii) {
8682 Shader* shader = GetShader(shaders[ii]);
8684 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
8685 return error::kNoError;
8687 service_ids[ii] = shader->service_id();
8689 // TODO(gman): call glShaderBinary
8690 return error::kNoError;
8694 void GLES2DecoderImpl::DoSwapBuffers() {
8695 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8697 int this_frame_number = frame_number_++;
8698 // TRACE_EVENT for gpu tests:
8699 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
8700 TRACE_EVENT_SCOPE_THREAD,
8701 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8702 "width", (is_offscreen ? offscreen_size_.width() :
8703 surface_->GetSize().width()));
8704 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
8705 "offscreen", is_offscreen,
8706 "frame", this_frame_number);
8708 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8711 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8712 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8713 is_offscreen ? offscreen_size_ : surface_->GetSize());
8716 // If offscreen then don't actually SwapBuffers to the display. Just copy
8717 // the rendered frame to another frame buffer.
8719 TRACE_EVENT2("gpu", "Offscreen",
8720 "width", offscreen_size_.width(), "height", offscreen_size_.height());
8721 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8722 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8723 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8725 if (workarounds().needs_offscreen_buffer_workaround) {
8726 offscreen_saved_frame_buffer_->Create();
8730 // Allocate the offscreen saved color texture.
8731 DCHECK(offscreen_saved_color_format_);
8732 offscreen_saved_color_texture_->AllocateStorage(
8733 offscreen_size_, offscreen_saved_color_format_, false);
8735 offscreen_saved_frame_buffer_->AttachRenderTexture(
8736 offscreen_saved_color_texture_.get());
8737 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8738 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8739 GL_FRAMEBUFFER_COMPLETE) {
8740 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8741 << "because offscreen saved FBO was incomplete.";
8742 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8746 // Clear the offscreen color texture.
8747 // TODO(piman): Is this still necessary?
8749 ScopedFrameBufferBinder binder(this,
8750 offscreen_saved_frame_buffer_->id());
8751 glClearColor(0, 0, 0, 0);
8752 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8753 glDisable(GL_SCISSOR_TEST);
8754 glClear(GL_COLOR_BUFFER_BIT);
8755 RestoreClearState();
8759 UpdateParentTextureInfo();
8762 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
8764 ScopedGLErrorSuppressor suppressor(
8765 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
8767 if (IsOffscreenBufferMultisampled()) {
8768 // For multisampled buffers, resolve the frame buffer.
8769 ScopedResolvedFrameBufferBinder binder(this, true, false);
8771 ScopedFrameBufferBinder binder(this,
8772 offscreen_target_frame_buffer_->id());
8774 if (offscreen_target_buffer_preserved_) {
8775 // Copy the target frame buffer to the saved offscreen texture.
8776 offscreen_saved_color_texture_->Copy(
8777 offscreen_saved_color_texture_->size(),
8778 offscreen_saved_color_format_);
8780 // Flip the textures in the parent context via the texture manager.
8781 if (!!offscreen_saved_color_texture_info_.get())
8782 offscreen_saved_color_texture_info_->texture()->
8783 SetServiceId(offscreen_target_color_texture_->id());
8785 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8786 offscreen_target_frame_buffer_->AttachRenderTexture(
8787 offscreen_target_color_texture_.get());
8790 // Ensure the side effects of the copy are visible to the parent
8791 // context. There is no need to do this for ANGLE because it uses a
8792 // single D3D device for all contexts.
8797 TRACE_EVENT2("gpu", "Onscreen",
8798 "width", surface_->GetSize().width(),
8799 "height", surface_->GetSize().height());
8800 if (!surface_->SwapBuffers()) {
8801 LOG(ERROR) << "Context lost because SwapBuffers failed.";
8802 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8807 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
8808 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
8809 Bucket* bucket = GetBucket(c.bucket_id);
8810 if (!bucket || bucket->size() == 0) {
8811 return error::kInvalidArguments;
8813 typedef cmds::EnableFeatureCHROMIUM::Result Result;
8814 Result* result = GetSharedMemoryAs<Result*>(
8815 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8817 return error::kOutOfBounds;
8819 // Check that the client initialized the result.
8821 return error::kInvalidArguments;
8823 std::string feature_str;
8824 if (!bucket->GetAsString(&feature_str)) {
8825 return error::kInvalidArguments;
8828 // TODO(gman): make this some kind of table to function pointer thingy.
8829 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
8830 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8831 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
8832 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8833 // TODO(gman): decide how to remove the need for this const_cast.
8834 // I could make validators_ non const but that seems bad as this is the only
8835 // place it is needed. I could make some special friend class of validators
8836 // just to allow this to set them. That seems silly. I could refactor this
8837 // code to use the extension mechanism or the initialization attributes to
8838 // turn this feature on. Given that the only real point of this is to make
8839 // the conformance tests pass and given that there is lots of real work that
8840 // needs to be done it seems like refactoring for one to one of those
8841 // methods is a very low priority.
8842 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
8843 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8844 force_webgl_glsl_validation_ = true;
8845 InitializeShaderTranslator();
8847 return error::kNoError;
8850 *result = 1; // true.
8851 return error::kNoError;
8854 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8855 uint32 immediate_data_size,
8856 const cmds::GetRequestableExtensionsCHROMIUM& c) {
8857 Bucket* bucket = CreateBucket(c.bucket_id);
8858 scoped_refptr<FeatureInfo> info(new FeatureInfo());
8859 info->Initialize(disallowed_features_);
8860 bucket->SetFromString(info->extensions().c_str());
8861 return error::kNoError;
8864 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
8865 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
8866 Bucket* bucket = GetBucket(c.bucket_id);
8867 if (!bucket || bucket->size() == 0) {
8868 return error::kInvalidArguments;
8870 std::string feature_str;
8871 if (!bucket->GetAsString(&feature_str)) {
8872 return error::kInvalidArguments;
8875 bool desire_webgl_glsl_validation =
8876 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
8877 bool desire_standard_derivatives = false;
8878 bool desire_frag_depth = false;
8879 bool desire_draw_buffers = false;
8880 if (force_webgl_glsl_validation_) {
8881 desire_standard_derivatives =
8882 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
8884 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
8885 desire_draw_buffers =
8886 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
8889 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
8890 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
8891 desire_frag_depth != frag_depth_explicitly_enabled_ ||
8892 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
8893 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
8894 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
8895 frag_depth_explicitly_enabled_ |= desire_frag_depth;
8896 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
8897 InitializeShaderTranslator();
8900 UpdateCapabilities();
8902 return error::kNoError;
8905 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
8906 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
8907 GLuint count = c.count;
8909 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
8910 return error::kOutOfBounds;
8912 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
8913 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
8914 if (pnames == NULL) {
8915 return error::kOutOfBounds;
8918 // We have to copy them since we use them twice so the client
8919 // can't change them between the time we validate them and the time we use
8921 scoped_ptr<GLenum[]> enums(new GLenum[count]);
8922 memcpy(enums.get(), pnames, pnames_size);
8924 // Count up the space needed for the result.
8925 uint32 num_results = 0;
8926 for (GLuint ii = 0; ii < count; ++ii) {
8927 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
8929 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8930 "glGetMulitpleCHROMIUM", enums[ii], "pname");
8931 return error::kNoError;
8933 // Num will never be more than 4.
8935 if (!SafeAddUint32(num_results, num, &num_results)) {
8936 return error::kOutOfBounds;
8940 uint32 result_size = 0;
8941 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
8942 return error::kOutOfBounds;
8945 if (result_size != static_cast<uint32>(c.size)) {
8948 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
8949 return error::kNoError;
8952 GLint* results = GetSharedMemoryAs<GLint*>(
8953 c.results_shm_id, c.results_shm_offset, result_size);
8954 if (results == NULL) {
8955 return error::kOutOfBounds;
8958 // Check the results have been cleared in case the context was lost.
8959 for (uint32 ii = 0; ii < num_results; ++ii) {
8961 return error::kInvalidArguments;
8966 GLint* start = results;
8967 for (GLuint ii = 0; ii < count; ++ii) {
8968 GLsizei num_written = 0;
8969 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
8970 !GetHelper(enums[ii], results, &num_written)) {
8971 DoGetIntegerv(enums[ii], results);
8973 results += num_written;
8976 // Just to verify. Should this be a DCHECK?
8977 if (static_cast<uint32>(results - start) != num_results) {
8978 return error::kOutOfBounds;
8981 return error::kNoError;
8984 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
8985 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
8986 GLuint program_id = static_cast<GLuint>(c.program);
8987 uint32 bucket_id = c.bucket_id;
8988 Bucket* bucket = CreateBucket(bucket_id);
8989 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
8990 Program* program = NULL;
8991 program = GetProgram(program_id);
8992 if (!program || !program->IsValid()) {
8993 return error::kNoError;
8995 program->GetProgramInfo(program_manager(), bucket);
8996 return error::kNoError;
8999 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9000 switch (reset_status_) {
9002 // TODO(kbr): improve the precision of the error code in this case.
9003 // Consider delegating to context for error code if MakeCurrent fails.
9004 return error::kUnknown;
9005 case GL_GUILTY_CONTEXT_RESET_ARB:
9006 return error::kGuilty;
9007 case GL_INNOCENT_CONTEXT_RESET_ARB:
9008 return error::kInnocent;
9009 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9010 return error::kUnknown;
9014 return error::kUnknown;
9017 bool GLES2DecoderImpl::WasContextLost() {
9018 if (reset_status_ != GL_NO_ERROR) {
9021 if (context_->WasAllocatedUsingRobustnessExtension()) {
9022 GLenum status = GL_NO_ERROR;
9023 if (has_robustness_extension_)
9024 status = glGetGraphicsResetStatusARB();
9025 if (status != GL_NO_ERROR) {
9026 // The graphics card was reset. Signal a lost context to the application.
9027 reset_status_ = status;
9028 reset_by_robustness_extension_ = true;
9029 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9030 << " context lost via ARB/EXT_robustness. Reset status = "
9031 << GLES2Util::GetStringEnum(status);
9038 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9039 return WasContextLost() && reset_by_robustness_extension_;
9042 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9043 // Only loses the context once.
9044 if (reset_status_ != GL_NO_ERROR) {
9048 // Marks this context as lost.
9049 reset_status_ = reset_status;
9050 current_decoder_error_ = error::kLostContext;
9053 error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9054 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
9055 GLenum current = static_cast<GLenum>(c.current);
9056 GLenum other = static_cast<GLenum>(c.other);
9057 if (!validators_->reset_status.IsValid(current)) {
9058 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9059 "glLoseContextCHROMIUM", current, "current");
9061 if (!validators_->reset_status.IsValid(other)) {
9062 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
9064 group_->LoseContexts(other);
9065 reset_status_ = current;
9066 current_decoder_error_ = error::kLostContext;
9067 return error::kLostContext;
9070 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9071 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9072 return error::kUnknownCommand;
9075 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9076 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9077 if (wait_sync_point_callback_.is_null())
9078 return error::kNoError;
9080 return wait_sync_point_callback_.Run(c.sync_point) ?
9081 error::kNoError : error::kDeferCommandUntilLater;
9084 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9085 GLsizei n, const GLuint* client_ids) {
9086 for (GLsizei ii = 0; ii < n; ++ii) {
9087 if (query_manager_->GetQuery(client_ids[ii])) {
9091 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
9095 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9096 GLsizei n, const GLuint* client_ids) {
9097 for (GLsizei ii = 0; ii < n; ++ii) {
9098 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9099 if (query && !query->IsDeleted()) {
9100 if (query == state_.current_query.get()) {
9101 state_.current_query = NULL;
9103 query->Destroy(true);
9104 query_manager_->RemoveQuery(client_ids[ii]);
9109 bool GLES2DecoderImpl::ProcessPendingQueries() {
9110 if (query_manager_.get() == NULL) {
9113 if (!query_manager_->ProcessPendingQueries()) {
9114 current_decoder_error_ = error::kOutOfBounds;
9116 return query_manager_->HavePendingQueries();
9119 // Note that if there are no pending readpixels right now,
9120 // this function will call the callback immediately.
9121 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9122 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9123 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9129 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9130 while (!pending_readpixel_fences_.empty() &&
9131 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9132 std::vector<base::Closure> callbacks =
9133 pending_readpixel_fences_.front()->callbacks;
9134 pending_readpixel_fences_.pop();
9135 for (size_t i = 0; i < callbacks.size(); i++) {
9141 bool GLES2DecoderImpl::HasMoreIdleWork() {
9142 return !pending_readpixel_fences_.empty() ||
9143 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9146 void GLES2DecoderImpl::PerformIdleWork() {
9147 ProcessPendingReadPixels();
9148 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9150 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9151 ProcessFinishedAsyncTransfers();
9154 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9155 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9156 GLenum target = static_cast<GLenum>(c.target);
9157 GLuint client_id = static_cast<GLuint>(c.id);
9158 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9159 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9162 case GL_COMMANDS_ISSUED_CHROMIUM:
9163 case GL_LATENCY_QUERY_CHROMIUM:
9164 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9165 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9166 case GL_GET_ERROR_QUERY_CHROMIUM:
9169 if (!features().occlusion_query_boolean) {
9171 GL_INVALID_OPERATION, "glBeginQueryEXT",
9172 "not enabled for occlusion queries");
9173 return error::kNoError;
9178 // TODO(hubbe): Make it possible to have one query per type running at the
9180 if (state_.current_query.get()) {
9182 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9183 return error::kNoError;
9186 if (client_id == 0) {
9187 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9188 return error::kNoError;
9191 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9193 // TODO(gman): Decide if we need this check.
9195 // Checks id was made by glGenQueries
9197 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9198 // for all Query ids but from the POV of the command buffer service maybe
9201 // The client can enforce this. I don't think the service cares.
9203 // IdAllocatorInterface* id_allocator =
9204 // group_->GetIdAllocator(id_namespaces::kQueries);
9205 // if (!id_allocator->InUse(client_id)) {
9206 // LOCAL_SET_GL_ERROR(
9207 // GL_INVALID_OPERATION,
9208 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
9209 // return error::kNoError;
9211 query = query_manager_->CreateQuery(
9212 target, client_id, sync_shm_id, sync_shm_offset);
9215 if (query->target() != target) {
9217 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9218 return error::kNoError;
9219 } else if (query->shm_id() != sync_shm_id ||
9220 query->shm_offset() != sync_shm_offset) {
9221 DLOG(ERROR) << "Shared memory used by query not the same as before";
9222 return error::kInvalidArguments;
9225 if (!query_manager_->BeginQuery(query)) {
9226 return error::kOutOfBounds;
9229 state_.current_query = query;
9230 return error::kNoError;
9233 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9234 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9235 GLenum target = static_cast<GLenum>(c.target);
9236 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9238 if (!state_.current_query.get()) {
9240 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9241 return error::kNoError;
9243 if (state_.current_query->target() != target) {
9245 GL_INVALID_OPERATION,
9246 "glEndQueryEXT", "target does not match active query");
9247 return error::kNoError;
9250 if (!query_manager_->EndQuery(state_.current_query.get(), submit_count)) {
9251 return error::kOutOfBounds;
9254 query_manager_->ProcessPendingTransferQueries();
9256 state_.current_query = NULL;
9257 return error::kNoError;
9260 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9261 GLsizei n, const GLuint* client_ids) {
9262 for (GLsizei ii = 0; ii < n; ++ii) {
9263 if (GetVertexAttribManager(client_ids[ii])) {
9268 if (!features().native_vertex_array_object) {
9270 for (GLsizei ii = 0; ii < n; ++ii) {
9271 CreateVertexAttribManager(client_ids[ii], 0);
9274 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9276 glGenVertexArraysOES(n, service_ids.get());
9277 for (GLsizei ii = 0; ii < n; ++ii) {
9278 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9285 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9286 GLsizei n, const GLuint* client_ids) {
9287 for (GLsizei ii = 0; ii < n; ++ii) {
9288 VertexAttribManager* vao =
9289 GetVertexAttribManager(client_ids[ii]);
9290 if (vao && !vao->IsDeleted()) {
9291 if (state_.vertex_attrib_manager.get() == vao) {
9292 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
9294 RemoveVertexAttribManager(client_ids[ii]);
9299 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9300 VertexAttribManager* vao = NULL;
9301 GLuint service_id = 0;
9302 if (client_id != 0) {
9303 vao = GetVertexAttribManager(client_id);
9305 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9306 // only allows names that have been previously generated. As such, we do
9307 // not generate new names here.
9309 GL_INVALID_OPERATION,
9310 "glBindVertexArrayOES", "bad vertex array id.");
9311 current_decoder_error_ = error::kNoError;
9314 service_id = vao->service_id();
9317 vao = default_vertex_attrib_manager_.get();
9320 // Only set the VAO state if it's changed
9321 if (state_.vertex_attrib_manager.get() != vao) {
9322 state_.vertex_attrib_manager = vao;
9323 if (!features().native_vertex_array_object) {
9324 EmulateVertexArrayState();
9326 glBindVertexArrayOES(service_id);
9331 // Used when OES_vertex_array_object isn't natively supported
9332 void GLES2DecoderImpl::EmulateVertexArrayState() {
9333 // Setup the Vertex attribute state
9334 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9335 RestoreStateForAttrib(vv);
9338 // Setup the element buffer
9339 Buffer* element_array_buffer =
9340 state_.vertex_attrib_manager->element_array_buffer();
9341 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9342 element_array_buffer ? element_array_buffer->service_id() : 0);
9345 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9346 const VertexAttribManager* vao =
9347 GetVertexAttribManager(client_id);
9348 return vao && vao->IsValid() && !vao->IsDeleted();
9351 error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
9352 uint32 immediate_data_size,
9353 const cmds::CreateStreamTextureCHROMIUM& c) {
9354 if (!features().chromium_stream_texture) {
9356 GL_INVALID_OPERATION,
9357 "glOpenStreamTextureCHROMIUM", "not supported.");
9358 return error::kNoError;
9361 uint32 client_id = c.client_id;
9362 typedef cmds::CreateStreamTextureCHROMIUM::Result Result;
9363 Result* result = GetSharedMemoryAs<Result*>(
9364 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9367 return error::kOutOfBounds;
9369 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9373 "glCreateStreamTextureCHROMIUM", "bad texture id.");
9374 return error::kNoError;
9377 Texture* texture = texture_ref->texture();
9378 if (texture->IsStreamTexture()) {
9380 GL_INVALID_OPERATION,
9381 "glCreateStreamTextureCHROMIUM", "is already a stream texture.");
9382 return error::kNoError;
9385 if (texture->target() && texture->target() != GL_TEXTURE_EXTERNAL_OES) {
9387 GL_INVALID_OPERATION,
9388 "glCreateStreamTextureCHROMIUM",
9389 "is already bound to incompatible target.");
9390 return error::kNoError;
9393 if (!stream_texture_manager())
9394 return error::kInvalidArguments;
9396 GLuint object_id = stream_texture_manager()->CreateStreamTexture(
9397 texture->service_id(), client_id);
9400 texture_manager()->SetStreamTexture(texture_ref, true);
9404 "glCreateStreamTextureCHROMIUM", "failed to create platform texture.");
9407 *result = object_id;
9408 return error::kNoError;
9411 error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
9412 uint32 immediate_data_size,
9413 const cmds::DestroyStreamTextureCHROMIUM& c) {
9414 GLuint client_id = c.texture;
9415 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9416 if (texture_ref && texture_manager()->IsStreamTextureOwner(texture_ref)) {
9417 if (!stream_texture_manager())
9418 return error::kInvalidArguments;
9420 stream_texture_manager()->DestroyStreamTexture(texture_ref->service_id());
9421 texture_manager()->SetStreamTexture(texture_ref, false);
9425 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
9428 return error::kNoError;
9431 #if defined(OS_MACOSX)
9432 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9433 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9435 if (it != texture_to_io_surface_map_.end()) {
9436 // Found a previous IOSurface bound to this texture; release it.
9437 CFTypeRef surface = it->second;
9439 texture_to_io_surface_map_.erase(it);
9444 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9445 GLenum target, GLsizei width, GLsizei height,
9446 GLuint io_surface_id, GLuint plane) {
9447 #if defined(OS_MACOSX)
9448 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9450 GL_INVALID_OPERATION,
9451 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9455 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9456 if (!surface_support) {
9458 GL_INVALID_OPERATION,
9459 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
9463 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9464 // This might be supported in the future, and if we could require
9465 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9466 // could delete a lot of code. For now, perform strict validation so we
9467 // know what's going on.
9469 GL_INVALID_OPERATION,
9470 "glTexImageIOSurface2DCHROMIUM",
9471 "requires TEXTURE_RECTANGLE_ARB target");
9475 // Default target might be conceptually valid, but disallow it to avoid
9477 TextureRef* texture_ref =
9478 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9481 GL_INVALID_OPERATION,
9482 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9486 // Look up the new IOSurface. Note that because of asynchrony
9487 // between processes this might fail; during live resizing the
9488 // plugin process might allocate and release an IOSurface before
9489 // this process gets a chance to look it up. Hold on to any old
9490 // IOSurface in this case.
9491 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9494 GL_INVALID_OPERATION,
9495 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9499 // Release any IOSurface previously bound to this texture.
9500 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9502 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9503 texture_to_io_surface_map_.insert(
9504 std::make_pair(texture_ref->service_id(), surface));
9506 CGLContextObj context =
9507 static_cast<CGLContextObj>(context_->GetHandle());
9509 CGLError err = surface_support->CGLTexImageIOSurface2D(
9516 GL_UNSIGNED_INT_8_8_8_8_REV,
9520 if (err != kCGLNoError) {
9522 GL_INVALID_OPERATION,
9523 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9527 texture_manager()->SetLevelInfo(
9528 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9529 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9532 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9533 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9537 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9538 switch (internalformat) {
9549 case GL_LUMINANCE8_ALPHA8_EXT:
9550 return GL_LUMINANCE_ALPHA;
9551 case GL_LUMINANCE8_EXT:
9552 return GL_LUMINANCE;
9555 case GL_RGBA32F_EXT:
9559 case GL_ALPHA32F_EXT:
9561 case GL_LUMINANCE32F_EXT:
9562 return GL_LUMINANCE;
9563 case GL_LUMINANCE_ALPHA32F_EXT:
9564 return GL_LUMINANCE_ALPHA;
9565 case GL_RGBA16F_EXT:
9569 case GL_ALPHA16F_EXT:
9571 case GL_LUMINANCE16F_EXT:
9572 return GL_LUMINANCE;
9573 case GL_LUMINANCE_ALPHA16F_EXT:
9574 return GL_LUMINANCE_ALPHA;
9582 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9583 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9584 GLenum internal_format, GLenum dest_type) {
9585 TextureRef* dest_texture_ref = GetTexture(dest_id);
9586 TextureRef* source_texture_ref = GetTexture(source_id);
9588 if (!source_texture_ref || !dest_texture_ref) {
9590 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9594 if (GL_TEXTURE_2D != target) {
9596 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9600 Texture* source_texture = source_texture_ref->texture();
9601 Texture* dest_texture = dest_texture_ref->texture();
9602 if (dest_texture->target() != GL_TEXTURE_2D ||
9603 (source_texture->target() != GL_TEXTURE_2D &&
9604 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9605 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9606 "glCopyTextureCHROMIUM",
9607 "invalid texture target binding");
9611 int source_width, source_height, dest_width, dest_height;
9613 if (source_texture->IsStreamTexture()) {
9614 DCHECK_EQ(source_texture->target(),
9615 static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES));
9616 DCHECK(stream_texture_manager());
9617 StreamTexture* stream_tex =
9618 stream_texture_manager()->LookupStreamTexture(
9619 source_texture->service_id());
9623 "glCopyTextureChromium", "Stream texture lookup failed");
9626 gfx::Size size = stream_tex->GetSize();
9627 source_width = size.width();
9628 source_height = size.height();
9629 if (source_width <= 0 || source_height <= 0) {
9632 "glCopyTextureChromium", "invalid streamtexture size");
9636 if (!source_texture->GetLevelSize(
9637 source_texture->target(), 0, &source_width, &source_height)) {
9638 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9639 "glCopyTextureChromium",
9640 "source texture has no level 0");
9644 // Check that this type of texture is allowed.
9645 if (!texture_manager()->ValidForTarget(
9646 source_texture->target(), level, source_width, source_height, 1)) {
9648 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9653 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9654 // needed because it takes 10s of milliseconds to initialize.
9655 if (!copy_texture_CHROMIUM_.get()) {
9656 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9657 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9658 copy_texture_CHROMIUM_->Initialize(this);
9659 RestoreCurrentFramebufferBindings();
9660 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9664 GLenum dest_type_previous;
9665 GLenum dest_internal_format;
9666 bool dest_level_defined = dest_texture->GetLevelSize(
9667 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9669 if (dest_level_defined) {
9670 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9671 &dest_internal_format);
9674 // Resize the destination texture to the dimensions of the source texture.
9675 if (!dest_level_defined || dest_width != source_width ||
9676 dest_height != source_height ||
9677 dest_internal_format != internal_format ||
9678 dest_type_previous != dest_type) {
9679 // Ensure that the glTexImage2D succeeds.
9680 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9681 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9683 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9684 0, internal_format, dest_type, NULL);
9685 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9686 if (error != GL_NO_ERROR) {
9687 RestoreCurrentTexture2DBindings(&state_);
9691 texture_manager()->SetLevelInfo(
9692 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9693 source_height, 1, 0, internal_format, dest_type, true);
9695 texture_manager()->SetLevelCleared(
9696 dest_texture_ref, GL_TEXTURE_2D, level, true);
9699 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9701 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9702 // before presenting.
9703 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9704 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9705 // instead of using default matrix crbug.com/226218.
9706 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9707 0.0f, 1.0f, 0.0f, 0.0f,
9708 0.0f, 0.0f, 1.0f, 0.0f,
9709 0.0f, 0.0f, 0.0f, 1.0f};
9710 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9712 source_texture->target(),
9713 dest_texture->target(),
9714 source_texture->service_id(),
9715 dest_texture->service_id(), level,
9716 source_width, source_height,
9718 unpack_premultiply_alpha_,
9719 unpack_unpremultiply_alpha_,
9722 copy_texture_CHROMIUM_->DoCopyTexture(
9724 source_texture->target(),
9725 dest_texture->target(),
9726 source_texture->service_id(),
9727 dest_texture->service_id(), level,
9728 source_width, source_height,
9730 unpack_premultiply_alpha_,
9731 unpack_unpremultiply_alpha_);
9734 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
9737 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9738 switch (internalformat) {
9740 return GL_UNSIGNED_SHORT_5_6_5;
9742 return GL_UNSIGNED_SHORT_4_4_4_4;
9744 return GL_UNSIGNED_SHORT_5_5_5_1;
9746 return GL_UNSIGNED_BYTE;
9748 return GL_UNSIGNED_BYTE;
9749 case GL_LUMINANCE8_ALPHA8_EXT:
9750 return GL_UNSIGNED_BYTE;
9751 case GL_LUMINANCE8_EXT:
9752 return GL_UNSIGNED_BYTE;
9754 return GL_UNSIGNED_BYTE;
9755 case GL_RGBA32F_EXT:
9759 case GL_ALPHA32F_EXT:
9761 case GL_LUMINANCE32F_EXT:
9763 case GL_LUMINANCE_ALPHA32F_EXT:
9765 case GL_RGBA16F_EXT:
9766 return GL_HALF_FLOAT_OES;
9768 return GL_HALF_FLOAT_OES;
9769 case GL_ALPHA16F_EXT:
9770 return GL_HALF_FLOAT_OES;
9771 case GL_LUMINANCE16F_EXT:
9772 return GL_HALF_FLOAT_OES;
9773 case GL_LUMINANCE_ALPHA16F_EXT:
9774 return GL_HALF_FLOAT_OES;
9776 return GL_UNSIGNED_BYTE;
9782 void GLES2DecoderImpl::DoTexStorage2DEXT(
9785 GLenum internal_format,
9788 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
9789 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
9790 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
9792 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
9795 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9799 GL_INVALID_OPERATION,
9800 "glTexStorage2DEXT", "unknown texture for target");
9803 Texture* texture = texture_ref->texture();
9804 if (texture->IsAttachedToFramebuffer()) {
9805 framebuffer_state_.clear_state_dirty = true;
9807 if (texture->IsImmutable()) {
9809 GL_INVALID_OPERATION,
9810 "glTexStorage2DEXT", "texture is immutable");
9814 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9815 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9818 GLsizei level_width = width;
9819 GLsizei level_height = height;
9820 uint32 estimated_size = 0;
9821 for (int ii = 0; ii < levels; ++ii) {
9822 uint32 level_size = 0;
9823 if (!GLES2Util::ComputeImageDataSizes(
9824 level_width, level_height, format, type, state_.unpack_alignment,
9825 &estimated_size, NULL, NULL) ||
9826 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
9828 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
9831 level_width = std::max(1, level_width >> 1);
9832 level_height = std::max(1, level_height >> 1);
9834 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9836 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
9841 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
9842 glTexStorage2DEXT(target, levels, internal_format, width, height);
9843 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
9844 if (error == GL_NO_ERROR) {
9845 GLsizei level_width = width;
9846 GLsizei level_height = height;
9847 for (int ii = 0; ii < levels; ++ii) {
9848 texture_manager()->SetLevelInfo(
9849 texture_ref, target, ii, format,
9850 level_width, level_height, 1, 0, format, type, false);
9851 level_width = std::max(1, level_width >> 1);
9852 level_height = std::max(1, level_height >> 1);
9854 texture->SetImmutable(true);
9858 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
9859 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
9860 return error::kUnknownCommand;
9863 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9864 const GLbyte* mailbox) {
9865 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
9866 "context", logger_.GetLogPrefix(),
9867 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9869 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9873 GL_INVALID_OPERATION,
9874 "glProduceTextureCHROMIUM", "unknown texture for target");
9878 Texture* produced = texture_manager()->Produce(texture_ref);
9881 GL_INVALID_OPERATION,
9882 "glProduceTextureCHROMIUM", "invalid texture");
9886 if (!group_->mailbox_manager()->ProduceTexture(
9888 *reinterpret_cast<const MailboxName*>(mailbox),
9891 GL_INVALID_OPERATION,
9892 "glProduceTextureCHROMIUM", "invalid mailbox name");
9897 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9898 const GLbyte* mailbox) {
9899 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
9900 "context", logger_.GetLogPrefix(),
9901 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9903 scoped_refptr<TextureRef> texture_ref =
9904 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9905 if (!texture_ref.get()) {
9906 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9907 "glConsumeTextureCHROMIUM",
9908 "unknown texture for target");
9911 GLuint client_id = texture_ref->client_id();
9914 GL_INVALID_OPERATION,
9915 "glConsumeTextureCHROMIUM", "unknown texture for target");
9919 group_->mailbox_manager()->ConsumeTexture(
9921 *reinterpret_cast<const MailboxName*>(mailbox));
9924 GL_INVALID_OPERATION,
9925 "glConsumeTextureCHROMIUM", "invalid mailbox name");
9928 if (texture->target() != target) {
9930 GL_INVALID_OPERATION,
9931 "glConsumeTextureCHROMIUM", "invalid target");
9935 DeleteTexturesHelper(1, &client_id);
9936 texture_ref = texture_manager()->Consume(client_id, texture);
9937 glBindTexture(target, texture_ref->service_id());
9939 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
9940 unit.bind_target = target;
9943 unit.bound_texture_2d = texture_ref;
9945 case GL_TEXTURE_CUBE_MAP:
9946 unit.bound_texture_cube_map = texture_ref;
9948 case GL_TEXTURE_EXTERNAL_OES:
9949 unit.bound_texture_external_oes = texture_ref;
9951 case GL_TEXTURE_RECTANGLE_ARB:
9952 unit.bound_texture_rectangle_arb = texture_ref;
9955 NOTREACHED(); // Validation should prevent us getting here.
9960 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
9961 GLsizei length, const GLchar* marker) {
9965 debug_marker_manager_.SetMarker(
9966 length ? std::string(marker, length) : std::string(marker));
9969 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
9970 GLsizei length, const GLchar* marker) {
9974 debug_marker_manager_.PushGroup(
9975 length ? std::string(marker, length) : std::string(marker));
9978 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
9979 debug_marker_manager_.PopGroup();
9982 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
9983 GLenum target, GLint image_id) {
9984 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
9985 if (target != GL_TEXTURE_2D) {
9986 // This might be supported in the future.
9988 GL_INVALID_OPERATION,
9989 "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
9993 // Default target might be conceptually valid, but disallow it to avoid
9995 TextureRef* texture_ref =
9996 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9999 GL_INVALID_OPERATION,
10000 "glBindTexImage2DCHROMIUM", "no texture bound");
10004 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10006 LOCAL_SET_GL_ERROR(
10007 GL_INVALID_OPERATION,
10008 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10013 ScopedGLErrorSuppressor suppressor(
10014 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10015 if (!gl_image->BindTexImage()) {
10016 LOCAL_SET_GL_ERROR(
10017 GL_INVALID_OPERATION,
10018 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10023 gfx::Size size = gl_image->GetSize();
10024 texture_manager()->SetLevelInfo(
10025 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10026 GL_RGBA, GL_UNSIGNED_BYTE, true);
10027 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10030 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10031 GLenum target, GLint image_id) {
10032 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10033 if (target != GL_TEXTURE_2D) {
10034 // This might be supported in the future.
10035 LOCAL_SET_GL_ERROR(
10036 GL_INVALID_OPERATION,
10037 "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10041 // Default target might be conceptually valid, but disallow it to avoid
10043 TextureRef* texture_ref =
10044 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10045 if (!texture_ref) {
10046 LOCAL_SET_GL_ERROR(
10047 GL_INVALID_OPERATION,
10048 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10052 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10054 LOCAL_SET_GL_ERROR(
10055 GL_INVALID_OPERATION,
10056 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10060 // Do nothing when image is not currently bound.
10061 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10065 ScopedGLErrorSuppressor suppressor(
10066 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10067 gl_image->ReleaseTexImage();
10070 texture_manager()->SetLevelInfo(
10071 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10072 GL_RGBA, GL_UNSIGNED_BYTE, false);
10075 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10076 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10077 Bucket* bucket = GetBucket(c.bucket_id);
10078 if (!bucket || bucket->size() == 0) {
10079 return error::kInvalidArguments;
10081 std::string command_name;
10082 if (!bucket->GetAsString(&command_name)) {
10083 return error::kInvalidArguments;
10085 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10086 if (!gpu_tracer_->Begin(command_name)) {
10087 LOCAL_SET_GL_ERROR(
10088 GL_INVALID_OPERATION,
10089 "glTraceBeginCHROMIUM", "unable to create begin trace");
10090 return error::kNoError;
10092 return error::kNoError;
10095 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10096 if (gpu_tracer_->CurrentName().empty()) {
10097 LOCAL_SET_GL_ERROR(
10098 GL_INVALID_OPERATION,
10099 "glTraceEndCHROMIUM", "no trace begin found");
10102 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10103 gpu_tracer_->End();
10106 void GLES2DecoderImpl::DoDrawBuffersEXT(
10107 GLsizei count, const GLenum* bufs) {
10108 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10109 LOCAL_SET_GL_ERROR(
10111 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10115 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10117 for (GLsizei i = 0; i < count; ++i) {
10118 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10119 bufs[i] != GL_NONE) {
10120 LOCAL_SET_GL_ERROR(
10121 GL_INVALID_OPERATION,
10122 "glDrawBuffersEXT",
10123 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10127 glDrawBuffersARB(count, bufs);
10128 framebuffer->SetDrawBuffers(count, bufs);
10129 } else { // backbuffer
10131 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10132 LOCAL_SET_GL_ERROR(
10133 GL_INVALID_OPERATION,
10134 "glDrawBuffersEXT",
10135 "more than one buffer or bufs not GL_NONE or GL_BACK");
10138 GLenum mapped_buf = bufs[0];
10139 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10140 bufs[0] == GL_BACK) {
10141 mapped_buf = GL_COLOR_ATTACHMENT0;
10143 glDrawBuffersARB(count, &mapped_buf);
10144 group_->set_draw_buffer(bufs[0]);
10148 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10149 const char* function_name,
10150 TextureRef* texture_ref,
10153 const void * data) {
10154 // We only support async uploads to 2D textures for now.
10155 if (GL_TEXTURE_2D != target) {
10156 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10159 // We only support uploads to level zero for now.
10161 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10164 // A transfer buffer must be bound, even for asyncTexImage2D.
10165 if (data == NULL) {
10166 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10169 // We only support one async transfer in progress.
10170 if (!texture_ref ||
10171 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10172 LOCAL_SET_GL_ERROR(
10173 GL_INVALID_OPERATION,
10174 function_name, "transfer already in progress");
10180 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10181 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10182 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10183 GLenum target = static_cast<GLenum>(c.target);
10184 GLint level = static_cast<GLint>(c.level);
10185 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10186 // unsigned integer for internalformat.
10187 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10188 GLsizei width = static_cast<GLsizei>(c.width);
10189 GLsizei height = static_cast<GLsizei>(c.height);
10190 GLint border = static_cast<GLint>(c.border);
10191 GLenum format = static_cast<GLenum>(c.format);
10192 GLenum type = static_cast<GLenum>(c.type);
10193 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10194 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10195 uint32 pixels_size;
10197 // TODO(epenner): Move this and copies of this memory validation
10198 // into ValidateTexImage2D step.
10199 if (!GLES2Util::ComputeImageDataSizes(
10200 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10202 return error::kOutOfBounds;
10204 const void* pixels = NULL;
10205 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10206 pixels = GetSharedMemoryAs<const void*>(
10207 pixels_shm_id, pixels_shm_offset, pixels_size);
10209 return error::kOutOfBounds;
10213 TextureManager::DoTextImage2DArguments args = {
10214 target, level, internal_format, width, height, border, format, type,
10215 pixels, pixels_size};
10216 TextureRef* texture_ref;
10217 // All the normal glTexSubImage2D validation.
10218 if (!texture_manager()->ValidateTexImage2D(
10219 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10220 return error::kNoError;
10223 // Extra async validation.
10224 Texture* texture = texture_ref->texture();
10225 if (!ValidateAsyncTransfer(
10226 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10227 return error::kNoError;
10229 // Don't allow async redefinition of a textures.
10230 if (texture->IsDefined()) {
10231 LOCAL_SET_GL_ERROR(
10232 GL_INVALID_OPERATION,
10233 "glAsyncTexImage2DCHROMIUM", "already defined");
10234 return error::kNoError;
10237 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10238 LOCAL_SET_GL_ERROR(
10239 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10240 return error::kNoError;
10243 // We know the memory/size is safe, so get the real shared memory since
10244 // it might need to be duped to prevent use-after-free of the memory.
10245 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
10246 base::SharedMemory* shared_memory = buffer.shared_memory;
10247 uint32 shm_size = buffer.size;
10248 uint32 shm_data_offset = c.pixels_shm_offset;
10249 uint32 shm_data_size = pixels_size;
10251 // Setup the parameters.
10252 AsyncTexImage2DParams tex_params = {
10253 target, level, static_cast<GLenum>(internal_format),
10254 width, height, border, format, type};
10255 AsyncMemoryParams mem_params = {
10256 shared_memory, shm_size, shm_data_offset, shm_data_size};
10258 // Set up the async state if needed, and make the texture
10259 // immutable so the async state stays valid. The level info
10260 // is set up lazily when the transfer completes.
10261 AsyncPixelTransferDelegate* delegate =
10262 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10264 texture->SetImmutable(true);
10266 delegate->AsyncTexImage2D(
10269 base::Bind(&TextureManager::SetLevelInfoFromParams,
10270 // The callback is only invoked if the transfer delegate still
10271 // exists, which implies through manager->texture_ref->state
10272 // ownership that both of these pointers are valid.
10273 base::Unretained(texture_manager()),
10274 base::Unretained(texture_ref),
10276 return error::kNoError;
10279 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10280 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10281 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10282 GLenum target = static_cast<GLenum>(c.target);
10283 GLint level = static_cast<GLint>(c.level);
10284 GLint xoffset = static_cast<GLint>(c.xoffset);
10285 GLint yoffset = static_cast<GLint>(c.yoffset);
10286 GLsizei width = static_cast<GLsizei>(c.width);
10287 GLsizei height = static_cast<GLsizei>(c.height);
10288 GLenum format = static_cast<GLenum>(c.format);
10289 GLenum type = static_cast<GLenum>(c.type);
10291 // TODO(epenner): Move this and copies of this memory validation
10292 // into ValidateTexSubImage2D step.
10294 if (!GLES2Util::ComputeImageDataSizes(
10295 width, height, format, type, state_.unpack_alignment, &data_size,
10297 return error::kOutOfBounds;
10299 const void* pixels = GetSharedMemoryAs<const void*>(
10300 c.data_shm_id, c.data_shm_offset, data_size);
10302 // All the normal glTexSubImage2D validation.
10303 error::Error error = error::kNoError;
10304 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10305 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10309 // Extra async validation.
10310 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10312 Texture* texture = texture_ref->texture();
10313 if (!ValidateAsyncTransfer(
10314 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10315 return error::kNoError;
10317 // Guarantee async textures are always 'cleared' as follows:
10318 // - AsyncTexImage2D can not redefine an existing texture
10319 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10320 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10321 // - Textures become immutable after an async call.
10322 // This way we know in all cases that an async texture is always clear.
10323 if (!texture->SafeToRenderFrom()) {
10324 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10326 LOCAL_SET_GL_ERROR(
10328 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10329 return error::kNoError;
10333 // We know the memory/size is safe, so get the real shared memory since
10334 // it might need to be duped to prevent use-after-free of the memory.
10335 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
10336 base::SharedMemory* shared_memory = buffer.shared_memory;
10337 uint32 shm_size = buffer.size;
10338 uint32 shm_data_offset = c.data_shm_offset;
10339 uint32 shm_data_size = data_size;
10341 // Setup the parameters.
10342 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10343 width, height, format, type};
10344 AsyncMemoryParams mem_params = {shared_memory, shm_size,
10345 shm_data_offset, shm_data_size};
10346 AsyncPixelTransferDelegate* delegate =
10347 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10349 // TODO(epenner): We may want to enforce exclusive use
10350 // of async APIs in which case this should become an error,
10351 // (the texture should have been async defined).
10352 AsyncTexImage2DParams define_params = {target, level,
10354 texture->GetLevelSize(target, level, &define_params.width,
10355 &define_params.height);
10356 texture->GetLevelType(target, level, &define_params.type,
10357 &define_params.internal_format);
10358 // Set up the async state if needed, and make the texture
10359 // immutable so the async state stays valid.
10360 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10361 texture_ref, define_params);
10362 texture->SetImmutable(true);
10365 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10366 return error::kNoError;
10369 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10370 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10371 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10372 GLenum target = static_cast<GLenum>(c.target);
10374 if (GL_TEXTURE_2D != target) {
10375 LOCAL_SET_GL_ERROR(
10376 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10377 return error::kNoError;
10379 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10381 if (!texture_ref) {
10382 LOCAL_SET_GL_ERROR(
10383 GL_INVALID_OPERATION,
10384 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10385 return error::kNoError;
10387 AsyncPixelTransferDelegate* delegate =
10388 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10390 LOCAL_SET_GL_ERROR(
10391 GL_INVALID_OPERATION,
10392 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10393 return error::kNoError;
10395 delegate->WaitForTransferCompletion();
10396 ProcessFinishedAsyncTransfers();
10397 return error::kNoError;
10400 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10401 TextureRef* texture_ref) {
10402 Texture* texture = texture_ref->texture();
10403 DoDidUseTexImageIfNeeded(texture, texture->target());
10406 // Include the auto-generated part of this file. We split this because it means
10407 // we can easily edit the non-auto generated parts right here in this file
10408 // instead of having to edit some template or the code generator.
10409 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10411 } // namespace gles2