Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blobd5f1e354492b85bf9d8e25d93999fb3220ffc8f6
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"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <list>
11 #include <map>
12 #include <stack>
13 #include <string>
14 #include <vector>
16 #include "base/at_exit.h"
17 #include "base/bind.h"
18 #include "base/callback_helpers.h"
19 #include "base/command_line.h"
20 #include "base/debug/trace_event.h"
21 #include "base/debug/trace_event_synthetic_delay.h"
22 #include "base/float_util.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/numerics/safe_math.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_split.h"
27 #include "build/build_config.h"
28 #define GLES2_GPU_SERVICE 1
29 #include "gpu/command_buffer/common/debug_marker_manager.h"
30 #include "gpu/command_buffer/common/gles2_cmd_format.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/mailbox.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
36 #include "gpu/command_buffer/service/buffer_manager.h"
37 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
38 #include "gpu/command_buffer/service/context_group.h"
39 #include "gpu/command_buffer/service/context_state.h"
40 #include "gpu/command_buffer/service/error_state.h"
41 #include "gpu/command_buffer/service/feature_info.h"
42 #include "gpu/command_buffer/service/framebuffer_manager.h"
43 #include "gpu/command_buffer/service/gl_utils.h"
44 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
45 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
46 #include "gpu/command_buffer/service/gpu_state_tracer.h"
47 #include "gpu/command_buffer/service/gpu_switches.h"
48 #include "gpu/command_buffer/service/gpu_tracer.h"
49 #include "gpu/command_buffer/service/image_manager.h"
50 #include "gpu/command_buffer/service/mailbox_manager.h"
51 #include "gpu/command_buffer/service/memory_tracking.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/shader_translator_cache.h"
58 #include "gpu/command_buffer/service/texture_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "third_party/smhasher/src/City.h"
62 #include "ui/gl/gl_fence.h"
63 #include "ui/gl/gl_image.h"
64 #include "ui/gl/gl_implementation.h"
65 #include "ui/gl/gl_surface.h"
67 #if defined(OS_MACOSX)
68 #include <IOSurface/IOSurfaceAPI.h>
69 // Note that this must be included after gl_bindings.h to avoid conflicts.
70 #include <OpenGL/CGLIOSurface.h>
71 #endif
73 #if defined(OS_WIN)
74 #include "base/win/win_util.h"
75 #endif
77 namespace gpu {
78 namespace gles2 {
80 namespace {
82 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
83 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
84 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
85 static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
87 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
88 GLint rangeMax,
89 GLint precision) {
90 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
93 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
94 GLenum precision_type,
95 GLint *range, GLint *precision) {
96 switch (precision_type) {
97 case GL_LOW_INT:
98 case GL_MEDIUM_INT:
99 case GL_HIGH_INT:
100 // These values are for a 32-bit twos-complement integer format.
101 range[0] = 31;
102 range[1] = 30;
103 *precision = 0;
104 break;
105 case GL_LOW_FLOAT:
106 case GL_MEDIUM_FLOAT:
107 case GL_HIGH_FLOAT:
108 // These values are for an IEEE single-precision floating-point format.
109 range[0] = 127;
110 range[1] = 127;
111 *precision = 23;
112 break;
113 default:
114 NOTREACHED();
115 break;
118 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
119 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
120 // This function is sometimes defined even though it's really just
121 // a stub, so we need to set range and precision as if it weren't
122 // defined before calling it.
123 // On Mac OS with some GPUs, calling this generates a
124 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
125 // platforms.
126 glGetShaderPrecisionFormat(shader_type, precision_type,
127 range, precision);
129 // TODO(brianderson): Make the following official workarounds.
131 // Some drivers have bugs where they report the ranges as a negative number.
132 // Taking the absolute value here shouldn't hurt because negative numbers
133 // aren't expected anyway.
134 range[0] = abs(range[0]);
135 range[1] = abs(range[1]);
137 // If the driver reports a precision for highp float that isn't actually
138 // highp, don't pretend like it's supported because shader compilation will
139 // fail anyway.
140 if (precision_type == GL_HIGH_FLOAT &&
141 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
142 range[0] = 0;
143 range[1] = 0;
144 *precision = 0;
149 static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
150 switch (plane_transform) {
151 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
152 return gfx::OVERLAY_TRANSFORM_NONE;
153 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
154 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
155 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
156 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
157 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
158 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
159 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
160 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
161 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
162 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
163 default:
164 return gfx::OVERLAY_TRANSFORM_INVALID;
168 } // namespace
170 class GLES2DecoderImpl;
172 // Local versions of the SET_GL_ERROR macros
173 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
174 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
175 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
176 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
177 function_name, value, label)
178 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
179 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
180 function_name, pname)
181 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
182 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
183 function_name)
184 #define LOCAL_PEEK_GL_ERROR(function_name) \
185 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
186 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
187 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
188 #define LOCAL_PERFORMANCE_WARNING(msg) \
189 PerformanceWarning(__FILE__, __LINE__, msg)
190 #define LOCAL_RENDER_WARNING(msg) \
191 RenderWarning(__FILE__, __LINE__, msg)
193 // Check that certain assumptions the code makes are true. There are places in
194 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
195 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
196 // a few others) are 32bits. If they are not 32bits the code will have to change
197 // to call those GL functions with service side memory and then copy the results
198 // to shared memory, converting the sizes.
199 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
200 GLint_not_same_size_as_uint32);
201 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
202 GLint_not_same_size_as_uint32);
203 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
204 GLfloat_not_same_size_as_float);
206 // TODO(kbr): the use of this anonymous namespace core dumps the
207 // linker on Mac OS X 10.6 when the symbol ordering file is used
208 // namespace {
210 // Returns the address of the first byte after a struct.
211 template <typename T>
212 const void* AddressAfterStruct(const T& pod) {
213 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
216 // Returns the address of the frst byte after the struct or NULL if size >
217 // immediate_data_size.
218 template <typename RETURN_TYPE, typename COMMAND_TYPE>
219 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
220 uint32 size,
221 uint32 immediate_data_size) {
222 return (size <= immediate_data_size) ?
223 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
224 NULL;
227 // Computes the data size for certain gl commands like glUniform.
228 bool ComputeDataSize(
229 GLuint count,
230 size_t size,
231 unsigned int elements_per_unit,
232 uint32* dst) {
233 uint32 value;
234 if (!SafeMultiplyUint32(count, size, &value)) {
235 return false;
237 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
238 return false;
240 *dst = value;
241 return true;
244 // Return true if a character belongs to the ASCII subset as defined in
245 // GLSL ES 1.0 spec section 3.1.
246 static bool CharacterIsValidForGLES(unsigned char c) {
247 // Printing characters are valid except " $ ` @ \ ' DEL.
248 if (c >= 32 && c <= 126 &&
249 c != '"' &&
250 c != '$' &&
251 c != '`' &&
252 c != '@' &&
253 c != '\\' &&
254 c != '\'') {
255 return true;
257 // Horizontal tab, line feed, vertical tab, form feed, carriage return
258 // are also valid.
259 if (c >= 9 && c <= 13) {
260 return true;
263 return false;
266 static bool StringIsValidForGLES(const char* str) {
267 for (; *str; ++str) {
268 if (!CharacterIsValidForGLES(*str)) {
269 return false;
272 return true;
275 // This class prevents any GL errors that occur when it is in scope from
276 // being reported to the client.
277 class ScopedGLErrorSuppressor {
278 public:
279 explicit ScopedGLErrorSuppressor(
280 const char* function_name, ErrorState* error_state);
281 ~ScopedGLErrorSuppressor();
282 private:
283 const char* function_name_;
284 ErrorState* error_state_;
285 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
288 // Temporarily changes a decoder's bound texture and restore it when this
289 // object goes out of scope. Also temporarily switches to using active texture
290 // unit zero in case the client has changed that to something invalid.
291 class ScopedTextureBinder {
292 public:
293 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
294 ~ScopedTextureBinder();
296 private:
297 ContextState* state_;
298 GLenum target_;
299 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
302 // Temporarily changes a decoder's bound render buffer and restore it when this
303 // object goes out of scope.
304 class ScopedRenderBufferBinder {
305 public:
306 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
307 ~ScopedRenderBufferBinder();
309 private:
310 ContextState* state_;
311 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
314 // Temporarily changes a decoder's bound frame buffer and restore it when this
315 // object goes out of scope.
316 class ScopedFrameBufferBinder {
317 public:
318 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
319 ~ScopedFrameBufferBinder();
321 private:
322 GLES2DecoderImpl* decoder_;
323 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
326 // Temporarily changes a decoder's bound frame buffer to a resolved version of
327 // the multisampled offscreen render buffer if that buffer is multisampled, and,
328 // if it is bound or enforce_internal_framebuffer is true. If internal is
329 // true, the resolved framebuffer is not visible to the parent.
330 class ScopedResolvedFrameBufferBinder {
331 public:
332 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
333 bool enforce_internal_framebuffer,
334 bool internal);
335 ~ScopedResolvedFrameBufferBinder();
337 private:
338 GLES2DecoderImpl* decoder_;
339 bool resolve_and_bind_;
340 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
343 class ScopedModifyPixels {
344 public:
345 explicit ScopedModifyPixels(TextureRef* ref);
346 ~ScopedModifyPixels();
348 private:
349 TextureRef* ref_;
352 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
353 if (ref_)
354 ref_->texture()->OnWillModifyPixels();
357 ScopedModifyPixels::~ScopedModifyPixels() {
358 if (ref_)
359 ref_->texture()->OnDidModifyPixels();
362 class ScopedRenderTo {
363 public:
364 explicit ScopedRenderTo(Framebuffer* framebuffer);
365 ~ScopedRenderTo();
367 private:
368 const Framebuffer* framebuffer_;
371 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
372 : framebuffer_(framebuffer) {
373 if (framebuffer)
374 framebuffer_->OnWillRenderTo();
377 ScopedRenderTo::~ScopedRenderTo() {
378 if (framebuffer_)
379 framebuffer_->OnDidRenderTo();
382 // Encapsulates an OpenGL texture.
383 class BackTexture {
384 public:
385 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
386 ~BackTexture();
388 // Create a new render texture.
389 void Create();
391 // Set the initial size and format of a render texture or resize it.
392 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
394 // Copy the contents of the currently bound frame buffer.
395 void Copy(const gfx::Size& size, GLenum format);
397 // Destroy the render texture. This must be explicitly called before
398 // destroying this object.
399 void Destroy();
401 // Invalidate the texture. This can be used when a context is lost and it is
402 // not possible to make it current in order to free the resource.
403 void Invalidate();
405 GLuint id() const {
406 return id_;
409 gfx::Size size() const {
410 return size_;
413 private:
414 MemoryTypeTracker memory_tracker_;
415 ContextState* state_;
416 size_t bytes_allocated_;
417 GLuint id_;
418 gfx::Size size_;
419 DISALLOW_COPY_AND_ASSIGN(BackTexture);
422 // Encapsulates an OpenGL render buffer of any format.
423 class BackRenderbuffer {
424 public:
425 explicit BackRenderbuffer(
426 RenderbufferManager* renderbuffer_manager,
427 MemoryTracker* memory_tracker,
428 ContextState* state);
429 ~BackRenderbuffer();
431 // Create a new render buffer.
432 void Create();
434 // Set the initial size and format of a render buffer or resize it.
435 bool AllocateStorage(const FeatureInfo* feature_info,
436 const gfx::Size& size,
437 GLenum format,
438 GLsizei samples);
440 // Destroy the render buffer. This must be explicitly called before destroying
441 // this object.
442 void Destroy();
444 // Invalidate the render buffer. This can be used when a context is lost and
445 // it is not possible to make it current in order to free the resource.
446 void Invalidate();
448 GLuint id() const {
449 return id_;
452 private:
453 RenderbufferManager* renderbuffer_manager_;
454 MemoryTypeTracker memory_tracker_;
455 ContextState* state_;
456 size_t bytes_allocated_;
457 GLuint id_;
458 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
461 // Encapsulates an OpenGL frame buffer.
462 class BackFramebuffer {
463 public:
464 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
465 ~BackFramebuffer();
467 // Create a new frame buffer.
468 void Create();
470 // Attach a color render buffer to a frame buffer.
471 void AttachRenderTexture(BackTexture* texture);
473 // Attach a render buffer to a frame buffer. Note that this unbinds any
474 // currently bound frame buffer.
475 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
477 // Destroy the frame buffer. This must be explicitly called before destroying
478 // this object.
479 void Destroy();
481 // Invalidate the frame buffer. This can be used when a context is lost and it
482 // is not possible to make it current in order to free the resource.
483 void Invalidate();
485 // See glCheckFramebufferStatusEXT.
486 GLenum CheckStatus();
488 GLuint id() const {
489 return id_;
492 private:
493 GLES2DecoderImpl* decoder_;
494 GLuint id_;
495 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
498 struct FenceCallback {
499 explicit FenceCallback()
500 : fence(gfx::GLFence::Create()) {
501 DCHECK(fence);
503 std::vector<base::Closure> callbacks;
504 scoped_ptr<gfx::GLFence> fence;
507 class AsyncUploadTokenCompletionObserver
508 : public AsyncPixelTransferCompletionObserver {
509 public:
510 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
511 : async_upload_token_(async_upload_token) {
514 virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
515 DCHECK(mem_params.buffer().get());
516 void* data = mem_params.GetDataAddress();
517 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
518 sync->SetAsyncUploadToken(async_upload_token_);
521 private:
522 virtual ~AsyncUploadTokenCompletionObserver() {
525 uint32 async_upload_token_;
527 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
530 // } // anonymous namespace.
532 // static
533 const unsigned int GLES2Decoder::kDefaultStencilMask =
534 static_cast<unsigned int>(-1);
536 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
537 uint32* service_texture_id) {
538 return false;
541 GLES2Decoder::GLES2Decoder()
542 : initialized_(false),
543 debug_(false),
544 log_commands_(false) {
547 GLES2Decoder::~GLES2Decoder() {
550 void GLES2Decoder::BeginDecoding() {}
552 void GLES2Decoder::EndDecoding() {}
554 // This class implements GLES2Decoder so we don't have to expose all the GLES2
555 // cmd stuff to outside this class.
556 class GLES2DecoderImpl : public GLES2Decoder,
557 public FramebufferManager::TextureDetachObserver,
558 public ErrorStateClient {
559 public:
560 explicit GLES2DecoderImpl(ContextGroup* group);
561 virtual ~GLES2DecoderImpl();
563 // Overridden from AsyncAPIInterface.
564 virtual Error DoCommand(unsigned int command,
565 unsigned int arg_count,
566 const void* args) OVERRIDE;
568 virtual error::Error DoCommands(unsigned int num_commands,
569 const void* buffer,
570 int num_entries,
571 int* entries_processed) OVERRIDE;
573 template <bool DebugImpl>
574 error::Error DoCommandsImpl(unsigned int num_commands,
575 const void* buffer,
576 int num_entries,
577 int* entries_processed);
579 // Overridden from AsyncAPIInterface.
580 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
582 // Overridden from GLES2Decoder.
583 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
584 const scoped_refptr<gfx::GLContext>& context,
585 bool offscreen,
586 const gfx::Size& size,
587 const DisallowedFeatures& disallowed_features,
588 const std::vector<int32>& attribs) OVERRIDE;
589 virtual void Destroy(bool have_context) OVERRIDE;
590 virtual void SetSurface(
591 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
592 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
593 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
594 void UpdateParentTextureInfo();
595 virtual bool MakeCurrent() OVERRIDE;
596 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
597 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
598 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
599 virtual Capabilities GetCapabilities() OVERRIDE;
600 virtual void RestoreState(const ContextState* prev_state) OVERRIDE;
602 virtual void RestoreActiveTexture() const OVERRIDE {
603 state_.RestoreActiveTexture();
605 virtual void RestoreAllTextureUnitBindings(
606 const ContextState* prev_state) const OVERRIDE {
607 state_.RestoreAllTextureUnitBindings(prev_state);
609 virtual void RestoreActiveTextureUnitBinding(
610 unsigned int target) const OVERRIDE {
611 state_.RestoreActiveTextureUnitBinding(target);
613 virtual void RestoreBufferBindings() const OVERRIDE {
614 state_.RestoreBufferBindings();
616 virtual void RestoreGlobalState() const OVERRIDE {
617 state_.RestoreGlobalState(NULL);
619 virtual void RestoreProgramBindings() const OVERRIDE {
620 state_.RestoreProgramBindings();
622 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
623 state_.RestoreTextureUnitBindings(unit, NULL);
625 virtual void RestoreFramebufferBindings() const OVERRIDE;
626 virtual void RestoreRenderbufferBindings() OVERRIDE;
627 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
629 virtual void ClearAllAttributes() const OVERRIDE;
630 virtual void RestoreAllAttributes() const OVERRIDE;
632 virtual QueryManager* GetQueryManager() OVERRIDE {
633 return query_manager_.get();
635 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
636 return vertex_array_manager_.get();
638 virtual ImageManager* GetImageManager() OVERRIDE {
639 return image_manager_.get();
641 virtual bool ProcessPendingQueries() OVERRIDE;
642 virtual bool HasMoreIdleWork() OVERRIDE;
643 virtual void PerformIdleWork() OVERRIDE;
645 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
647 virtual void SetResizeCallback(
648 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
650 virtual Logger* GetLogger() OVERRIDE;
652 virtual void BeginDecoding() OVERRIDE;
653 virtual void EndDecoding() OVERRIDE;
655 virtual ErrorState* GetErrorState() OVERRIDE;
656 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
658 virtual void SetShaderCacheCallback(
659 const ShaderCacheCallback& callback) OVERRIDE;
660 virtual void SetWaitSyncPointCallback(
661 const WaitSyncPointCallback& callback) OVERRIDE;
663 virtual AsyncPixelTransferManager*
664 GetAsyncPixelTransferManager() OVERRIDE;
665 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
666 virtual void SetAsyncPixelTransferManagerForTest(
667 AsyncPixelTransferManager* manager) OVERRIDE;
668 virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
669 void ProcessFinishedAsyncTransfers();
671 virtual bool GetServiceTextureId(uint32 client_texture_id,
672 uint32* service_texture_id) OVERRIDE;
674 virtual uint32 GetTextureUploadCount() OVERRIDE;
675 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
676 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
677 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
679 // Restores the current state to the user's settings.
680 void RestoreCurrentFramebufferBindings();
682 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
683 void ApplyDirtyState();
685 // These check the state of the currently bound framebuffer or the
686 // backbuffer if no framebuffer is bound.
687 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
688 // check with all attached and enabled color attachments.
689 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
690 bool BoundFramebufferHasDepthAttachment();
691 bool BoundFramebufferHasStencilAttachment();
693 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
695 // Overridden from FramebufferManager::TextureDetachObserver:
696 virtual void OnTextureRefDetachedFromFramebuffer(
697 TextureRef* texture) OVERRIDE;
699 // Overriden from ErrorStateClient.
700 virtual void OnOutOfMemoryError() OVERRIDE;
702 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
703 void EnsureRenderbufferBound();
705 // Helpers to facilitate calling into compatible extensions.
706 static void RenderbufferStorageMultisampleHelper(
707 const FeatureInfo* feature_info,
708 GLenum target,
709 GLsizei samples,
710 GLenum internal_format,
711 GLsizei width,
712 GLsizei height);
714 void BlitFramebufferHelper(GLint srcX0,
715 GLint srcY0,
716 GLint srcX1,
717 GLint srcY1,
718 GLint dstX0,
719 GLint dstY0,
720 GLint dstX1,
721 GLint dstY1,
722 GLbitfield mask,
723 GLenum filter);
725 private:
726 friend class ScopedFrameBufferBinder;
727 friend class ScopedResolvedFrameBufferBinder;
728 friend class BackFramebuffer;
730 // Initialize or re-initialize the shader translator.
731 bool InitializeShaderTranslator();
733 void UpdateCapabilities();
735 // Helpers for the glGen and glDelete functions.
736 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
737 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
738 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
739 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
740 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
741 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
742 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
743 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
744 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
745 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
746 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
747 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
749 // Helper for async upload token completion notification callback.
750 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
751 uint32 sync_data_shm_id,
752 uint32 sync_data_shm_offset);
756 // Workarounds
757 void OnFboChanged() const;
758 void OnUseFramebuffer() const;
760 // TODO(gman): Cache these pointers?
761 BufferManager* buffer_manager() {
762 return group_->buffer_manager();
765 RenderbufferManager* renderbuffer_manager() {
766 return group_->renderbuffer_manager();
769 FramebufferManager* framebuffer_manager() {
770 return group_->framebuffer_manager();
773 ProgramManager* program_manager() {
774 return group_->program_manager();
777 ShaderManager* shader_manager() {
778 return group_->shader_manager();
781 ShaderTranslatorCache* shader_translator_cache() {
782 return group_->shader_translator_cache();
785 const TextureManager* texture_manager() const {
786 return group_->texture_manager();
789 TextureManager* texture_manager() {
790 return group_->texture_manager();
793 MailboxManager* mailbox_manager() {
794 return group_->mailbox_manager();
797 ImageManager* image_manager() { return image_manager_.get(); }
799 VertexArrayManager* vertex_array_manager() {
800 return vertex_array_manager_.get();
803 MemoryTracker* memory_tracker() {
804 return group_->memory_tracker();
807 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
808 MemoryTracker* tracker = memory_tracker();
809 if (tracker) {
810 return tracker->EnsureGPUMemoryAvailable(estimated_size);
812 return true;
815 bool IsOffscreenBufferMultisampled() const {
816 return offscreen_target_samples_ > 1;
819 // Creates a Texture for the given texture.
820 TextureRef* CreateTexture(
821 GLuint client_id, GLuint service_id) {
822 return texture_manager()->CreateTexture(client_id, service_id);
825 // Gets the texture info for the given texture. Returns NULL if none exists.
826 TextureRef* GetTexture(GLuint client_id) const {
827 return texture_manager()->GetTexture(client_id);
830 // Deletes the texture info for the given texture.
831 void RemoveTexture(GLuint client_id) {
832 texture_manager()->RemoveTexture(client_id);
835 // Get the size (in pixels) of the currently bound frame buffer (either FBO
836 // or regular back buffer).
837 gfx::Size GetBoundReadFrameBufferSize();
839 // Get the format of the currently bound frame buffer (either FBO or regular
840 // back buffer)
841 GLenum GetBoundReadFrameBufferTextureType();
842 GLenum GetBoundReadFrameBufferInternalFormat();
843 GLenum GetBoundDrawFrameBufferInternalFormat();
845 // Wrapper for CompressedTexImage2D commands.
846 error::Error DoCompressedTexImage2D(
847 GLenum target,
848 GLint level,
849 GLenum internal_format,
850 GLsizei width,
851 GLsizei height,
852 GLint border,
853 GLsizei image_size,
854 const void* data);
856 // Wrapper for CompressedTexSubImage2D.
857 void DoCompressedTexSubImage2D(
858 GLenum target,
859 GLint level,
860 GLint xoffset,
861 GLint yoffset,
862 GLsizei width,
863 GLsizei height,
864 GLenum format,
865 GLsizei imageSize,
866 const void * data);
868 // Wrapper for CopyTexImage2D.
869 void DoCopyTexImage2D(
870 GLenum target,
871 GLint level,
872 GLenum internal_format,
873 GLint x,
874 GLint y,
875 GLsizei width,
876 GLsizei height,
877 GLint border);
879 // Wrapper for SwapBuffers.
880 void DoSwapBuffers();
882 // Wrapper for CopyTexSubImage2D.
883 void DoCopyTexSubImage2D(
884 GLenum target,
885 GLint level,
886 GLint xoffset,
887 GLint yoffset,
888 GLint x,
889 GLint y,
890 GLsizei width,
891 GLsizei height);
893 // Validation for TexSubImage2D.
894 bool ValidateTexSubImage2D(
895 error::Error* error,
896 const char* function_name,
897 GLenum target,
898 GLint level,
899 GLint xoffset,
900 GLint yoffset,
901 GLsizei width,
902 GLsizei height,
903 GLenum format,
904 GLenum type,
905 const void * data);
907 // Wrapper for TexSubImage2D.
908 error::Error DoTexSubImage2D(
909 GLenum target,
910 GLint level,
911 GLint xoffset,
912 GLint yoffset,
913 GLsizei width,
914 GLsizei height,
915 GLenum format,
916 GLenum type,
917 const void * data);
919 // Extra validation for async tex(Sub)Image2D.
920 bool ValidateAsyncTransfer(
921 const char* function_name,
922 TextureRef* texture_ref,
923 GLenum target,
924 GLint level,
925 const void * data);
927 // Wrapper for TexImageIOSurface2DCHROMIUM.
928 void DoTexImageIOSurface2DCHROMIUM(
929 GLenum target,
930 GLsizei width,
931 GLsizei height,
932 GLuint io_surface_id,
933 GLuint plane);
935 void DoCopyTextureCHROMIUM(
936 GLenum target,
937 GLuint source_id,
938 GLuint target_id,
939 GLint level,
940 GLenum internal_format,
941 GLenum dest_type);
943 // Wrapper for TexStorage2DEXT.
944 void DoTexStorage2DEXT(
945 GLenum target,
946 GLint levels,
947 GLenum internal_format,
948 GLsizei width,
949 GLsizei height);
951 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
952 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
953 const GLbyte* key);
954 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
955 GLenum target, const GLbyte* data);
957 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
958 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
959 GLuint client_id);
961 void DoBindTexImage2DCHROMIUM(
962 GLenum target,
963 GLint image_id);
964 void DoReleaseTexImage2DCHROMIUM(
965 GLenum target,
966 GLint image_id);
968 void DoTraceEndCHROMIUM(void);
970 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
972 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
974 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
975 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
977 // Creates a Program for the given program.
978 Program* CreateProgram(
979 GLuint client_id, GLuint service_id) {
980 return program_manager()->CreateProgram(client_id, service_id);
983 // Gets the program info for the given program. Returns NULL if none exists.
984 Program* GetProgram(GLuint client_id) {
985 return program_manager()->GetProgram(client_id);
988 #if defined(NDEBUG)
989 void LogClientServiceMapping(
990 const char* /* function_name */,
991 GLuint /* client_id */,
992 GLuint /* service_id */) {
994 template<typename T>
995 void LogClientServiceForInfo(
996 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
998 #else
999 void LogClientServiceMapping(
1000 const char* function_name, GLuint client_id, GLuint service_id) {
1001 if (service_logging_) {
1002 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1003 << ": client_id = " << client_id
1004 << ", service_id = " << service_id;
1007 template<typename T>
1008 void LogClientServiceForInfo(
1009 T* info, GLuint client_id, const char* function_name) {
1010 if (info) {
1011 LogClientServiceMapping(function_name, client_id, info->service_id());
1014 #endif
1016 // Gets the program info for the given program. If it's not a program
1017 // generates a GL error. Returns NULL if not program.
1018 Program* GetProgramInfoNotShader(
1019 GLuint client_id, const char* function_name) {
1020 Program* program = GetProgram(client_id);
1021 if (!program) {
1022 if (GetShader(client_id)) {
1023 LOCAL_SET_GL_ERROR(
1024 GL_INVALID_OPERATION, function_name, "shader passed for program");
1025 } else {
1026 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1029 LogClientServiceForInfo(program, client_id, function_name);
1030 return program;
1034 // Creates a Shader for the given shader.
1035 Shader* CreateShader(
1036 GLuint client_id,
1037 GLuint service_id,
1038 GLenum shader_type) {
1039 return shader_manager()->CreateShader(
1040 client_id, service_id, shader_type);
1043 // Gets the shader info for the given shader. Returns NULL if none exists.
1044 Shader* GetShader(GLuint client_id) {
1045 return shader_manager()->GetShader(client_id);
1048 // Gets the shader info for the given shader. If it's not a shader generates a
1049 // GL error. Returns NULL if not shader.
1050 Shader* GetShaderInfoNotProgram(
1051 GLuint client_id, const char* function_name) {
1052 Shader* shader = GetShader(client_id);
1053 if (!shader) {
1054 if (GetProgram(client_id)) {
1055 LOCAL_SET_GL_ERROR(
1056 GL_INVALID_OPERATION, function_name, "program passed for shader");
1057 } else {
1058 LOCAL_SET_GL_ERROR(
1059 GL_INVALID_VALUE, function_name, "unknown shader");
1062 LogClientServiceForInfo(shader, client_id, function_name);
1063 return shader;
1066 // Creates a buffer info for the given buffer.
1067 void CreateBuffer(GLuint client_id, GLuint service_id) {
1068 return buffer_manager()->CreateBuffer(client_id, service_id);
1071 // Gets the buffer info for the given buffer.
1072 Buffer* GetBuffer(GLuint client_id) {
1073 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1074 return buffer;
1077 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1078 // on glDeleteBuffers so we can make sure the user does not try to render
1079 // with deleted buffers.
1080 void RemoveBuffer(GLuint client_id);
1082 // Creates a framebuffer info for the given framebuffer.
1083 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1084 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1087 // Gets the framebuffer info for the given framebuffer.
1088 Framebuffer* GetFramebuffer(GLuint client_id) {
1089 return framebuffer_manager()->GetFramebuffer(client_id);
1092 // Removes the framebuffer info for the given framebuffer.
1093 void RemoveFramebuffer(GLuint client_id) {
1094 framebuffer_manager()->RemoveFramebuffer(client_id);
1097 // Creates a renderbuffer info for the given renderbuffer.
1098 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1099 return renderbuffer_manager()->CreateRenderbuffer(
1100 client_id, service_id);
1103 // Gets the renderbuffer info for the given renderbuffer.
1104 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1105 return renderbuffer_manager()->GetRenderbuffer(client_id);
1108 // Removes the renderbuffer info for the given renderbuffer.
1109 void RemoveRenderbuffer(GLuint client_id) {
1110 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1113 // Gets the vertex attrib manager for the given vertex array.
1114 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1115 VertexAttribManager* info =
1116 vertex_array_manager()->GetVertexAttribManager(client_id);
1117 return info;
1120 // Removes the vertex attrib manager for the given vertex array.
1121 void RemoveVertexAttribManager(GLuint client_id) {
1122 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1125 // Creates a vertex attrib manager for the given vertex array.
1126 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1127 GLuint client_id,
1128 GLuint service_id,
1129 bool client_visible) {
1130 return vertex_array_manager()->CreateVertexAttribManager(
1131 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1134 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1135 void DoBindUniformLocationCHROMIUM(
1136 GLuint client_id, GLint location, const char* name);
1138 error::Error GetAttribLocationHelper(
1139 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1140 const std::string& name_str);
1142 error::Error GetUniformLocationHelper(
1143 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1144 const std::string& name_str);
1146 // Helper for glShaderSource.
1147 error::Error ShaderSourceHelper(
1148 GLuint client_id, const char* data, uint32 data_size);
1150 // Clear any textures used by the current program.
1151 bool ClearUnclearedTextures();
1153 // Clears any uncleared attachments attached to the given frame buffer.
1154 // Returns false if there was a generated GL error.
1155 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1157 // overridden from GLES2Decoder
1158 virtual bool ClearLevel(unsigned service_id,
1159 unsigned bind_target,
1160 unsigned target,
1161 int level,
1162 unsigned internal_format,
1163 unsigned format,
1164 unsigned type,
1165 int width,
1166 int height,
1167 bool is_texture_immutable) OVERRIDE;
1169 // Restore all GL state that affects clearing.
1170 void RestoreClearState();
1172 // Remembers the state of some capabilities.
1173 // Returns: true if glEnable/glDisable should actually be called.
1174 bool SetCapabilityState(GLenum cap, bool enabled);
1176 // Check that the currently bound framebuffers are valid.
1177 // Generates GL error if not.
1178 bool CheckBoundFramebuffersValid(const char* func_name);
1180 // Check that the currently bound read framebuffer has a color image
1181 // attached. Generates GL error if not.
1182 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1184 // Check if a framebuffer meets our requirements.
1185 bool CheckFramebufferValid(
1186 Framebuffer* framebuffer,
1187 GLenum target,
1188 const char* func_name);
1190 // Checks if the current program exists and is valid. If not generates the
1191 // appropriate GL error. Returns true if the current program is in a usable
1192 // state.
1193 bool CheckCurrentProgram(const char* function_name);
1195 // Checks if the current program exists and is valid and that location is not
1196 // -1. If the current program is not valid generates the appropriate GL
1197 // error. Returns true if the current program is in a usable state and
1198 // location is not -1.
1199 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1201 // Gets the type of a uniform for a location in the current program. Sets GL
1202 // errors if the current program is not valid. Returns true if the current
1203 // program is valid and the location exists. Adjusts count so it
1204 // does not overflow the uniform.
1205 bool PrepForSetUniformByLocation(GLint fake_location,
1206 const char* function_name,
1207 Program::UniformApiType api_type,
1208 GLint* real_location,
1209 GLenum* type,
1210 GLsizei* count);
1212 // Gets the service id for any simulated backbuffer fbo.
1213 GLuint GetBackbufferServiceId() const;
1215 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1216 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1218 // Helper for glGetVertexAttrib
1219 void GetVertexAttribHelper(
1220 const VertexAttrib* attrib, GLenum pname, GLint* param);
1222 // Wrapper for glCreateProgram
1223 bool CreateProgramHelper(GLuint client_id);
1225 // Wrapper for glCreateShader
1226 bool CreateShaderHelper(GLenum type, GLuint client_id);
1228 // Wrapper for glActiveTexture
1229 void DoActiveTexture(GLenum texture_unit);
1231 // Wrapper for glAttachShader
1232 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1234 // Wrapper for glBindBuffer since we need to track the current targets.
1235 void DoBindBuffer(GLenum target, GLuint buffer);
1237 // Wrapper for glBindFramebuffer since we need to track the current targets.
1238 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1240 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1241 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1243 // Wrapper for glBindTexture since we need to track the current targets.
1244 void DoBindTexture(GLenum target, GLuint texture);
1246 // Wrapper for glBindVertexArrayOES
1247 void DoBindVertexArrayOES(GLuint array);
1248 void EmulateVertexArrayState();
1250 // Wrapper for glBlitFramebufferCHROMIUM.
1251 void DoBlitFramebufferCHROMIUM(
1252 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1253 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1254 GLbitfield mask, GLenum filter);
1256 // Wrapper for glBufferSubData.
1257 void DoBufferSubData(
1258 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1260 // Wrapper for glCheckFramebufferStatus
1261 GLenum DoCheckFramebufferStatus(GLenum target);
1263 // Wrapper for glClear
1264 error::Error DoClear(GLbitfield mask);
1266 // Wrappers for various state.
1267 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1268 void DoSampleCoverage(GLclampf value, GLboolean invert);
1270 // Wrapper for glCompileShader.
1271 void DoCompileShader(GLuint shader);
1273 // Helper for DeleteSharedIdsCHROMIUM commands.
1274 void DoDeleteSharedIdsCHROMIUM(
1275 GLuint namespace_id, GLsizei n, const GLuint* ids);
1277 // Wrapper for glDetachShader
1278 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1280 // Wrapper for glDisable
1281 void DoDisable(GLenum cap);
1283 // Wrapper for glDisableVertexAttribArray.
1284 void DoDisableVertexAttribArray(GLuint index);
1286 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1287 // attachments.
1288 void DoDiscardFramebufferEXT(GLenum target,
1289 GLsizei numAttachments,
1290 const GLenum* attachments);
1292 // Wrapper for glEnable
1293 void DoEnable(GLenum cap);
1295 // Wrapper for glEnableVertexAttribArray.
1296 void DoEnableVertexAttribArray(GLuint index);
1298 // Wrapper for glFinish.
1299 void DoFinish();
1301 // Wrapper for glFlush.
1302 void DoFlush();
1304 // Wrapper for glFramebufferRenderbufffer.
1305 void DoFramebufferRenderbuffer(
1306 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1307 GLuint renderbuffer);
1309 // Wrapper for glFramebufferTexture2D.
1310 void DoFramebufferTexture2D(
1311 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1312 GLint level);
1314 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1315 void DoFramebufferTexture2DMultisample(
1316 GLenum target, GLenum attachment, GLenum textarget,
1317 GLuint texture, GLint level, GLsizei samples);
1319 // Common implementation for both DoFramebufferTexture2D wrappers.
1320 void DoFramebufferTexture2DCommon(const char* name,
1321 GLenum target, GLenum attachment, GLenum textarget,
1322 GLuint texture, GLint level, GLsizei samples);
1324 // Wrapper for glGenerateMipmap
1325 void DoGenerateMipmap(GLenum target);
1327 // Helper for GenSharedIdsCHROMIUM commands.
1328 void DoGenSharedIdsCHROMIUM(
1329 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1331 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1332 // to account for different pname values defined in different extension
1333 // variants.
1334 GLenum AdjustGetPname(GLenum pname);
1336 // Wrapper for DoGetBooleanv.
1337 void DoGetBooleanv(GLenum pname, GLboolean* params);
1339 // Wrapper for DoGetFloatv.
1340 void DoGetFloatv(GLenum pname, GLfloat* params);
1342 // Wrapper for glGetFramebufferAttachmentParameteriv.
1343 void DoGetFramebufferAttachmentParameteriv(
1344 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1346 // Wrapper for glGetIntegerv.
1347 void DoGetIntegerv(GLenum pname, GLint* params);
1349 // Gets the max value in a range in a buffer.
1350 GLuint DoGetMaxValueInBufferCHROMIUM(
1351 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1353 // Wrapper for glGetBufferParameteriv.
1354 void DoGetBufferParameteriv(
1355 GLenum target, GLenum pname, GLint* params);
1357 // Wrapper for glGetProgramiv.
1358 void DoGetProgramiv(
1359 GLuint program_id, GLenum pname, GLint* params);
1361 // Wrapper for glRenderbufferParameteriv.
1362 void DoGetRenderbufferParameteriv(
1363 GLenum target, GLenum pname, GLint* params);
1365 // Wrapper for glGetShaderiv
1366 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1368 // Wrappers for glGetTexParameter.
1369 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1370 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1371 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1373 // Wrappers for glGetVertexAttrib.
1374 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1375 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1377 // Wrappers for glIsXXX functions.
1378 bool DoIsEnabled(GLenum cap);
1379 bool DoIsBuffer(GLuint client_id);
1380 bool DoIsFramebuffer(GLuint client_id);
1381 bool DoIsProgram(GLuint client_id);
1382 bool DoIsRenderbuffer(GLuint client_id);
1383 bool DoIsShader(GLuint client_id);
1384 bool DoIsTexture(GLuint client_id);
1385 bool DoIsVertexArrayOES(GLuint client_id);
1387 // Wrapper for glLinkProgram
1388 void DoLinkProgram(GLuint program);
1390 // Helper for RegisterSharedIdsCHROMIUM.
1391 void DoRegisterSharedIdsCHROMIUM(
1392 GLuint namespace_id, GLsizei n, const GLuint* ids);
1394 // Wrapper for glRenderbufferStorage.
1395 void DoRenderbufferStorage(
1396 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1398 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1399 void DoRenderbufferStorageMultisampleCHROMIUM(
1400 GLenum target, GLsizei samples, GLenum internalformat,
1401 GLsizei width, GLsizei height);
1403 // Handler for glRenderbufferStorageMultisampleEXT
1404 // (multisampled_render_to_texture).
1405 void DoRenderbufferStorageMultisampleEXT(
1406 GLenum target, GLsizei samples, GLenum internalformat,
1407 GLsizei width, GLsizei height);
1409 // Common validation for multisample extensions.
1410 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1411 GLenum internalformat,
1412 GLsizei width,
1413 GLsizei height);
1415 // Verifies that the currently bound multisample renderbuffer is valid
1416 // Very slow! Only done on platforms with driver bugs that return invalid
1417 // buffers under memory pressure
1418 bool VerifyMultisampleRenderbufferIntegrity(
1419 GLuint renderbuffer, GLenum format);
1421 // Wrapper for glReleaseShaderCompiler.
1422 void DoReleaseShaderCompiler() { }
1424 // Wrappers for glTexParameter functions.
1425 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1426 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1427 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1428 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1430 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1431 // spec only these 2 functions can be used to set sampler uniforms.
1432 void DoUniform1i(GLint fake_location, GLint v0);
1433 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1434 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1435 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1436 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1438 // Wrappers for glUniformfv because some drivers don't correctly accept
1439 // bool uniforms.
1440 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1441 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1442 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1443 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1445 void DoUniformMatrix2fv(
1446 GLint fake_location, GLsizei count, GLboolean transpose,
1447 const GLfloat* value);
1448 void DoUniformMatrix3fv(
1449 GLint fake_location, GLsizei count, GLboolean transpose,
1450 const GLfloat* value);
1451 void DoUniformMatrix4fv(
1452 GLint fake_location, GLsizei count, GLboolean transpose,
1453 const GLfloat* value);
1455 bool SetVertexAttribValue(
1456 const char* function_name, GLuint index, const GLfloat* value);
1458 // Wrappers for glVertexAttrib??
1459 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1460 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1461 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1462 void DoVertexAttrib4f(
1463 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1464 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1465 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1466 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1467 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1469 // Wrapper for glViewport
1470 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1472 // Wrapper for glUseProgram
1473 void DoUseProgram(GLuint program);
1475 // Wrapper for glValidateProgram.
1476 void DoValidateProgram(GLuint program_client_id);
1478 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1479 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1480 void DoPopGroupMarkerEXT(void);
1482 // Gets the number of values that will be returned by glGetXXX. Returns
1483 // false if pname is unknown.
1484 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1486 // Checks if the current program and vertex attributes are valid for drawing.
1487 bool IsDrawValid(
1488 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1489 GLsizei primcount);
1491 // Returns true if successful, simulated will be true if attrib0 was
1492 // simulated.
1493 bool SimulateAttrib0(
1494 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1495 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1497 // If an image is bound to texture, this will call Will/DidUseTexImage
1498 // if needed.
1499 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1500 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1502 // Returns false if textures were replaced.
1503 bool PrepareTexturesForRender();
1504 void RestoreStateForTextures();
1506 // Returns true if GL_FIXED attribs were simulated.
1507 bool SimulateFixedAttribs(
1508 const char* function_name,
1509 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1510 void RestoreStateForSimulatedFixedAttribs();
1512 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1513 // cases (primcount is always 1 for non-instanced).
1514 error::Error DoDrawArrays(
1515 const char* function_name,
1516 bool instanced, GLenum mode, GLint first, GLsizei count,
1517 GLsizei primcount);
1518 error::Error DoDrawElements(
1519 const char* function_name,
1520 bool instanced, GLenum mode, GLsizei count, GLenum type,
1521 int32 offset, GLsizei primcount);
1523 GLenum GetBindTargetForSamplerType(GLenum type) {
1524 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1525 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1526 switch (type) {
1527 case GL_SAMPLER_2D:
1528 return GL_TEXTURE_2D;
1529 case GL_SAMPLER_CUBE:
1530 return GL_TEXTURE_CUBE_MAP;
1531 case GL_SAMPLER_EXTERNAL_OES:
1532 return GL_TEXTURE_EXTERNAL_OES;
1533 case GL_SAMPLER_2D_RECT_ARB:
1534 return GL_TEXTURE_RECTANGLE_ARB;
1537 NOTREACHED();
1538 return 0;
1541 // Gets the framebuffer info for a particular target.
1542 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1543 Framebuffer* framebuffer = NULL;
1544 switch (target) {
1545 case GL_FRAMEBUFFER:
1546 case GL_DRAW_FRAMEBUFFER_EXT:
1547 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1548 break;
1549 case GL_READ_FRAMEBUFFER_EXT:
1550 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1551 break;
1552 default:
1553 NOTREACHED();
1554 break;
1556 return framebuffer;
1559 Renderbuffer* GetRenderbufferInfoForTarget(
1560 GLenum target) {
1561 Renderbuffer* renderbuffer = NULL;
1562 switch (target) {
1563 case GL_RENDERBUFFER:
1564 renderbuffer = state_.bound_renderbuffer.get();
1565 break;
1566 default:
1567 NOTREACHED();
1568 break;
1570 return renderbuffer;
1573 // Validates the program and location for a glGetUniform call and returns
1574 // a SizeResult setup to receive the result. Returns true if glGetUniform
1575 // should be called.
1576 bool GetUniformSetup(
1577 GLuint program, GLint fake_location,
1578 uint32 shm_id, uint32 shm_offset,
1579 error::Error* error, GLint* real_location, GLuint* service_id,
1580 void** result, GLenum* result_type);
1582 virtual bool WasContextLost() OVERRIDE;
1583 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1584 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1586 #if defined(OS_MACOSX)
1587 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1588 #endif
1590 bool ValidateCompressedTexDimensions(
1591 const char* function_name,
1592 GLint level, GLsizei width, GLsizei height, GLenum format);
1593 bool ValidateCompressedTexFuncData(
1594 const char* function_name,
1595 GLsizei width, GLsizei height, GLenum format, size_t size);
1596 bool ValidateCompressedTexSubDimensions(
1597 const char* function_name,
1598 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1599 GLsizei width, GLsizei height, GLenum format,
1600 Texture* texture);
1602 void RenderWarning(const char* filename, int line, const std::string& msg);
1603 void PerformanceWarning(
1604 const char* filename, int line, const std::string& msg);
1606 const FeatureInfo::FeatureFlags& features() const {
1607 return feature_info_->feature_flags();
1610 const FeatureInfo::Workarounds& workarounds() const {
1611 return feature_info_->workarounds();
1614 bool ShouldDeferDraws() {
1615 return !offscreen_target_frame_buffer_.get() &&
1616 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1617 surface_->DeferDraws();
1620 bool ShouldDeferReads() {
1621 return !offscreen_target_frame_buffer_.get() &&
1622 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1623 surface_->DeferDraws();
1626 error::Error WillAccessBoundFramebufferForDraw() {
1627 if (ShouldDeferDraws())
1628 return error::kDeferCommandUntilLater;
1629 if (!offscreen_target_frame_buffer_.get() &&
1630 !framebuffer_state_.bound_draw_framebuffer.get() &&
1631 !surface_->SetBackbufferAllocation(true))
1632 return error::kLostContext;
1633 return error::kNoError;
1636 error::Error WillAccessBoundFramebufferForRead() {
1637 if (ShouldDeferReads())
1638 return error::kDeferCommandUntilLater;
1639 if (!offscreen_target_frame_buffer_.get() &&
1640 !framebuffer_state_.bound_read_framebuffer.get() &&
1641 !surface_->SetBackbufferAllocation(true))
1642 return error::kLostContext;
1643 return error::kNoError;
1646 // Set remaining commands to process to 0 to force DoCommands to return
1647 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1648 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1650 void ProcessPendingReadPixels();
1651 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1653 // Generate a member function prototype for each command in an automated and
1654 // typesafe way.
1655 #define GLES2_CMD_OP(name) \
1656 Error Handle##name(uint32 immediate_data_size, const void* data);
1658 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1660 #undef GLES2_CMD_OP
1662 // The GL context this decoder renders to on behalf of the client.
1663 scoped_refptr<gfx::GLSurface> surface_;
1664 scoped_refptr<gfx::GLContext> context_;
1666 // The ContextGroup for this decoder uses to track resources.
1667 scoped_refptr<ContextGroup> group_;
1669 DebugMarkerManager debug_marker_manager_;
1670 Logger logger_;
1672 // All the state for this context.
1673 ContextState state_;
1675 // Current width and height of the offscreen frame buffer.
1676 gfx::Size offscreen_size_;
1678 // Util to help with GL.
1679 GLES2Util util_;
1681 // unpack flip y as last set by glPixelStorei
1682 bool unpack_flip_y_;
1684 // unpack (un)premultiply alpha as last set by glPixelStorei
1685 bool unpack_premultiply_alpha_;
1686 bool unpack_unpremultiply_alpha_;
1688 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1689 GLuint attrib_0_buffer_id_;
1691 // The value currently in attrib_0.
1692 Vec4 attrib_0_value_;
1694 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1695 bool attrib_0_buffer_matches_value_;
1697 // The size of attrib 0.
1698 GLsizei attrib_0_size_;
1700 // The buffer used to simulate GL_FIXED attribs.
1701 GLuint fixed_attrib_buffer_id_;
1703 // The size of fiixed attrib buffer.
1704 GLsizei fixed_attrib_buffer_size_;
1706 // The offscreen frame buffer that the client renders to. With EGL, the
1707 // depth and stencil buffers are separate. With regular GL there is a single
1708 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1709 // offscreen_target_stencil_render_buffer_ is unused.
1710 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1711 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1712 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1713 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1714 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1715 GLenum offscreen_target_color_format_;
1716 GLenum offscreen_target_depth_format_;
1717 GLenum offscreen_target_stencil_format_;
1718 GLsizei offscreen_target_samples_;
1719 GLboolean offscreen_target_buffer_preserved_;
1721 // The copy that is saved when SwapBuffers is called.
1722 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1723 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1724 scoped_refptr<TextureRef>
1725 offscreen_saved_color_texture_info_;
1727 // The copy that is used as the destination for multi-sample resolves.
1728 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1729 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1730 GLenum offscreen_saved_color_format_;
1732 scoped_ptr<QueryManager> query_manager_;
1734 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1736 scoped_ptr<ImageManager> image_manager_;
1738 base::Callback<void(gfx::Size, float)> resize_callback_;
1740 WaitSyncPointCallback wait_sync_point_callback_;
1742 ShaderCacheCallback shader_cache_callback_;
1744 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1746 // The format of the back buffer_
1747 GLenum back_buffer_color_format_;
1748 bool back_buffer_has_depth_;
1749 bool back_buffer_has_stencil_;
1751 // Backbuffer attachments that are currently undefined.
1752 uint32 backbuffer_needs_clear_bits_;
1754 // The current decoder error communicates the decoder error through command
1755 // processing functions that do not return the error value. Should be set only
1756 // if not returning an error.
1757 error::Error current_decoder_error_;
1759 bool use_shader_translator_;
1760 scoped_refptr<ShaderTranslator> vertex_translator_;
1761 scoped_refptr<ShaderTranslator> fragment_translator_;
1763 DisallowedFeatures disallowed_features_;
1765 // Cached from ContextGroup
1766 const Validators* validators_;
1767 scoped_refptr<FeatureInfo> feature_info_;
1769 int frame_number_;
1771 // Number of commands remaining to be processed in DoCommands().
1772 int commands_to_process_;
1774 bool has_robustness_extension_;
1775 GLenum reset_status_;
1776 bool reset_by_robustness_extension_;
1777 bool supports_post_sub_buffer_;
1779 // These flags are used to override the state of the shared feature_info_
1780 // member. Because the same FeatureInfo instance may be shared among many
1781 // contexts, the assumptions on the availablity of extensions in WebGL
1782 // contexts may be broken. These flags override the shared state to preserve
1783 // WebGL semantics.
1784 bool force_webgl_glsl_validation_;
1785 bool derivatives_explicitly_enabled_;
1786 bool frag_depth_explicitly_enabled_;
1787 bool draw_buffers_explicitly_enabled_;
1788 bool shader_texture_lod_explicitly_enabled_;
1790 bool compile_shader_always_succeeds_;
1792 // An optional behaviour to lose the context and group when OOM.
1793 bool lose_context_when_out_of_memory_;
1795 // Log extra info.
1796 bool service_logging_;
1798 #if defined(OS_MACOSX)
1799 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1800 TextureToIOSurfaceMap texture_to_io_surface_map_;
1801 #endif
1803 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1805 // Cached values of the currently assigned viewport dimensions.
1806 GLsizei viewport_max_width_;
1807 GLsizei viewport_max_height_;
1809 // Command buffer stats.
1810 base::TimeDelta total_processing_commands_time_;
1812 // States related to each manager.
1813 DecoderTextureState texture_state_;
1814 DecoderFramebufferState framebuffer_state_;
1816 scoped_ptr<GPUTracer> gpu_tracer_;
1817 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1818 const unsigned char* cb_command_trace_category_;
1819 int gpu_trace_level_;
1820 bool gpu_trace_commands_;
1821 bool gpu_debug_commands_;
1823 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1825 // Used to validate multisample renderbuffers if needed
1826 GLuint validation_texture_;
1827 GLuint validation_fbo_multisample_;
1828 GLuint validation_fbo_;
1830 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
1831 uint32 immediate_data_size,
1832 const void* data);
1834 // A struct to hold info about each command.
1835 struct CommandInfo {
1836 CmdHandler cmd_handler;
1837 uint8 arg_flags; // How to handle the arguments for this command
1838 uint8 cmd_flags; // How to handle this command
1839 uint16 arg_count; // How many arguments are expected for this command.
1842 // A table of CommandInfo for all the commands.
1843 static const CommandInfo command_info[kNumCommands - kStartPoint];
1845 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1848 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
1849 #define GLES2_CMD_OP(name) \
1851 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1852 cmds::name::cmd_flags, \
1853 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1855 , /* NOLINT */
1856 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1857 #undef GLES2_CMD_OP
1860 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1861 const char* function_name, ErrorState* error_state)
1862 : function_name_(function_name),
1863 error_state_(error_state) {
1864 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1867 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1868 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1871 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1872 TextureUnit& info = state->texture_units[0];
1873 GLuint last_id;
1874 scoped_refptr<TextureRef> texture_ref;
1875 switch (target) {
1876 case GL_TEXTURE_2D:
1877 texture_ref = info.bound_texture_2d;
1878 break;
1879 case GL_TEXTURE_CUBE_MAP:
1880 texture_ref = info.bound_texture_cube_map;
1881 break;
1882 case GL_TEXTURE_EXTERNAL_OES:
1883 texture_ref = info.bound_texture_external_oes;
1884 break;
1885 case GL_TEXTURE_RECTANGLE_ARB:
1886 texture_ref = info.bound_texture_rectangle_arb;
1887 break;
1888 default:
1889 NOTREACHED();
1890 break;
1892 if (texture_ref.get()) {
1893 last_id = texture_ref->service_id();
1894 } else {
1895 last_id = 0;
1898 glBindTexture(target, last_id);
1899 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1902 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1903 GLuint id,
1904 GLenum target)
1905 : state_(state),
1906 target_(target) {
1907 ScopedGLErrorSuppressor suppressor(
1908 "ScopedTextureBinder::ctor", state_->GetErrorState());
1910 // TODO(apatrick): Check if there are any other states that need to be reset
1911 // before binding a new texture.
1912 glActiveTexture(GL_TEXTURE0);
1913 glBindTexture(target, id);
1916 ScopedTextureBinder::~ScopedTextureBinder() {
1917 ScopedGLErrorSuppressor suppressor(
1918 "ScopedTextureBinder::dtor", state_->GetErrorState());
1919 RestoreCurrentTextureBindings(state_, target_);
1922 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1923 GLuint id)
1924 : state_(state) {
1925 ScopedGLErrorSuppressor suppressor(
1926 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1927 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1930 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1931 ScopedGLErrorSuppressor suppressor(
1932 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1933 state_->RestoreRenderbufferBindings();
1936 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1937 GLuint id)
1938 : decoder_(decoder) {
1939 ScopedGLErrorSuppressor suppressor(
1940 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1941 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1942 decoder->OnFboChanged();
1945 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1946 ScopedGLErrorSuppressor suppressor(
1947 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1948 decoder_->RestoreCurrentFramebufferBindings();
1951 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1952 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1953 : decoder_(decoder) {
1954 resolve_and_bind_ = (
1955 decoder_->offscreen_target_frame_buffer_.get() &&
1956 decoder_->IsOffscreenBufferMultisampled() &&
1957 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1958 enforce_internal_framebuffer));
1959 if (!resolve_and_bind_)
1960 return;
1962 ScopedGLErrorSuppressor suppressor(
1963 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1964 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1965 decoder_->offscreen_target_frame_buffer_->id());
1966 GLuint targetid;
1967 if (internal) {
1968 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1969 decoder_->offscreen_resolved_frame_buffer_.reset(
1970 new BackFramebuffer(decoder_));
1971 decoder_->offscreen_resolved_frame_buffer_->Create();
1972 decoder_->offscreen_resolved_color_texture_.reset(
1973 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1974 decoder_->offscreen_resolved_color_texture_->Create();
1976 DCHECK(decoder_->offscreen_saved_color_format_);
1977 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1978 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1979 false);
1980 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1981 decoder_->offscreen_resolved_color_texture_.get());
1982 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1983 GL_FRAMEBUFFER_COMPLETE) {
1984 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1985 << "because offscreen resolved FBO was incomplete.";
1986 return;
1989 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1990 } else {
1991 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1993 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1994 const int width = decoder_->offscreen_size_.width();
1995 const int height = decoder_->offscreen_size_.height();
1996 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
1997 decoder->BlitFramebufferHelper(0,
1999 width,
2000 height,
2003 width,
2004 height,
2005 GL_COLOR_BUFFER_BIT,
2006 GL_NEAREST);
2007 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2010 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2011 if (!resolve_and_bind_)
2012 return;
2014 ScopedGLErrorSuppressor suppressor(
2015 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2016 decoder_->RestoreCurrentFramebufferBindings();
2017 if (decoder_->state_.enable_flags.scissor_test) {
2018 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2022 BackTexture::BackTexture(
2023 MemoryTracker* memory_tracker,
2024 ContextState* state)
2025 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2026 state_(state),
2027 bytes_allocated_(0),
2028 id_(0) {
2031 BackTexture::~BackTexture() {
2032 // This does not destroy the render texture because that would require that
2033 // the associated GL context was current. Just check that it was explicitly
2034 // destroyed.
2035 DCHECK_EQ(id_, 0u);
2038 void BackTexture::Create() {
2039 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2040 state_->GetErrorState());
2041 Destroy();
2042 glGenTextures(1, &id_);
2043 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2044 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2045 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2046 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2047 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2049 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2050 // never called on an offscreen context, no data will ever be uploaded to the
2051 // saved offscreen color texture (it is deferred until to when SwapBuffers
2052 // is called). My idea is that some nvidia drivers might have a bug where
2053 // deleting a texture that has never been populated might cause a
2054 // crash.
2055 glTexImage2D(
2056 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2058 bytes_allocated_ = 16u * 16u * 4u;
2059 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2062 bool BackTexture::AllocateStorage(
2063 const gfx::Size& size, GLenum format, bool zero) {
2064 DCHECK_NE(id_, 0u);
2065 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2066 state_->GetErrorState());
2067 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2068 uint32 image_size = 0;
2069 GLES2Util::ComputeImageDataSizes(
2070 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
2071 NULL, NULL);
2073 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2074 return false;
2077 scoped_ptr<char[]> zero_data;
2078 if (zero) {
2079 zero_data.reset(new char[image_size]);
2080 memset(zero_data.get(), 0, image_size);
2083 glTexImage2D(GL_TEXTURE_2D,
2084 0, // mip level
2085 format,
2086 size.width(),
2087 size.height(),
2088 0, // border
2089 format,
2090 GL_UNSIGNED_BYTE,
2091 zero_data.get());
2093 size_ = size;
2095 bool success = glGetError() == GL_NO_ERROR;
2096 if (success) {
2097 memory_tracker_.TrackMemFree(bytes_allocated_);
2098 bytes_allocated_ = image_size;
2099 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2101 return success;
2104 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2105 DCHECK_NE(id_, 0u);
2106 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2107 state_->GetErrorState());
2108 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2109 glCopyTexImage2D(GL_TEXTURE_2D,
2110 0, // level
2111 format,
2112 0, 0,
2113 size.width(),
2114 size.height(),
2115 0); // border
2118 void BackTexture::Destroy() {
2119 if (id_ != 0) {
2120 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2121 state_->GetErrorState());
2122 glDeleteTextures(1, &id_);
2123 id_ = 0;
2125 memory_tracker_.TrackMemFree(bytes_allocated_);
2126 bytes_allocated_ = 0;
2129 void BackTexture::Invalidate() {
2130 id_ = 0;
2133 BackRenderbuffer::BackRenderbuffer(
2134 RenderbufferManager* renderbuffer_manager,
2135 MemoryTracker* memory_tracker,
2136 ContextState* state)
2137 : renderbuffer_manager_(renderbuffer_manager),
2138 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2139 state_(state),
2140 bytes_allocated_(0),
2141 id_(0) {
2144 BackRenderbuffer::~BackRenderbuffer() {
2145 // This does not destroy the render buffer because that would require that
2146 // the associated GL context was current. Just check that it was explicitly
2147 // destroyed.
2148 DCHECK_EQ(id_, 0u);
2151 void BackRenderbuffer::Create() {
2152 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2153 state_->GetErrorState());
2154 Destroy();
2155 glGenRenderbuffersEXT(1, &id_);
2158 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2159 const gfx::Size& size,
2160 GLenum format,
2161 GLsizei samples) {
2162 ScopedGLErrorSuppressor suppressor(
2163 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2164 ScopedRenderBufferBinder binder(state_, id_);
2166 uint32 estimated_size = 0;
2167 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2168 size.width(), size.height(), samples, format, &estimated_size)) {
2169 return false;
2172 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2173 return false;
2176 if (samples <= 1) {
2177 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2178 format,
2179 size.width(),
2180 size.height());
2181 } else {
2182 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2183 GL_RENDERBUFFER,
2184 samples,
2185 format,
2186 size.width(),
2187 size.height());
2189 bool success = glGetError() == GL_NO_ERROR;
2190 if (success) {
2191 // Mark the previously allocated bytes as free.
2192 memory_tracker_.TrackMemFree(bytes_allocated_);
2193 bytes_allocated_ = estimated_size;
2194 // Track the newly allocated bytes.
2195 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2197 return success;
2200 void BackRenderbuffer::Destroy() {
2201 if (id_ != 0) {
2202 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2203 state_->GetErrorState());
2204 glDeleteRenderbuffersEXT(1, &id_);
2205 id_ = 0;
2207 memory_tracker_.TrackMemFree(bytes_allocated_);
2208 bytes_allocated_ = 0;
2211 void BackRenderbuffer::Invalidate() {
2212 id_ = 0;
2215 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2216 : decoder_(decoder),
2217 id_(0) {
2220 BackFramebuffer::~BackFramebuffer() {
2221 // This does not destroy the frame buffer because that would require that
2222 // the associated GL context was current. Just check that it was explicitly
2223 // destroyed.
2224 DCHECK_EQ(id_, 0u);
2227 void BackFramebuffer::Create() {
2228 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2229 decoder_->GetErrorState());
2230 Destroy();
2231 glGenFramebuffersEXT(1, &id_);
2234 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2235 DCHECK_NE(id_, 0u);
2236 ScopedGLErrorSuppressor suppressor(
2237 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2238 ScopedFrameBufferBinder binder(decoder_, id_);
2239 GLuint attach_id = texture ? texture->id() : 0;
2240 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2241 GL_COLOR_ATTACHMENT0,
2242 GL_TEXTURE_2D,
2243 attach_id,
2247 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2248 BackRenderbuffer* render_buffer) {
2249 DCHECK_NE(id_, 0u);
2250 ScopedGLErrorSuppressor suppressor(
2251 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2252 ScopedFrameBufferBinder binder(decoder_, id_);
2253 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2254 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2255 target,
2256 GL_RENDERBUFFER,
2257 attach_id);
2260 void BackFramebuffer::Destroy() {
2261 if (id_ != 0) {
2262 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2263 decoder_->GetErrorState());
2264 glDeleteFramebuffersEXT(1, &id_);
2265 id_ = 0;
2269 void BackFramebuffer::Invalidate() {
2270 id_ = 0;
2273 GLenum BackFramebuffer::CheckStatus() {
2274 DCHECK_NE(id_, 0u);
2275 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2276 decoder_->GetErrorState());
2277 ScopedFrameBufferBinder binder(decoder_, id_);
2278 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2281 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2282 return new GLES2DecoderImpl(group);
2285 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2286 : GLES2Decoder(),
2287 group_(group),
2288 logger_(&debug_marker_manager_),
2289 state_(group_->feature_info(), this, &logger_),
2290 unpack_flip_y_(false),
2291 unpack_premultiply_alpha_(false),
2292 unpack_unpremultiply_alpha_(false),
2293 attrib_0_buffer_id_(0),
2294 attrib_0_buffer_matches_value_(true),
2295 attrib_0_size_(0),
2296 fixed_attrib_buffer_id_(0),
2297 fixed_attrib_buffer_size_(0),
2298 offscreen_target_color_format_(0),
2299 offscreen_target_depth_format_(0),
2300 offscreen_target_stencil_format_(0),
2301 offscreen_target_samples_(0),
2302 offscreen_target_buffer_preserved_(true),
2303 offscreen_saved_color_format_(0),
2304 back_buffer_color_format_(0),
2305 back_buffer_has_depth_(false),
2306 back_buffer_has_stencil_(false),
2307 backbuffer_needs_clear_bits_(0),
2308 current_decoder_error_(error::kNoError),
2309 use_shader_translator_(true),
2310 validators_(group_->feature_info()->validators()),
2311 feature_info_(group_->feature_info()),
2312 frame_number_(0),
2313 has_robustness_extension_(false),
2314 reset_status_(GL_NO_ERROR),
2315 reset_by_robustness_extension_(false),
2316 supports_post_sub_buffer_(false),
2317 force_webgl_glsl_validation_(false),
2318 derivatives_explicitly_enabled_(false),
2319 frag_depth_explicitly_enabled_(false),
2320 draw_buffers_explicitly_enabled_(false),
2321 shader_texture_lod_explicitly_enabled_(false),
2322 compile_shader_always_succeeds_(false),
2323 lose_context_when_out_of_memory_(false),
2324 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2325 switches::kEnableGPUServiceLoggingGPU)),
2326 viewport_max_width_(0),
2327 viewport_max_height_(0),
2328 texture_state_(group_->feature_info()
2329 ->workarounds()
2330 .texsubimage2d_faster_than_teximage2d),
2331 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2332 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2333 gpu_trace_level_(2),
2334 gpu_trace_commands_(false),
2335 gpu_debug_commands_(false),
2336 validation_texture_(0),
2337 validation_fbo_multisample_(0),
2338 validation_fbo_(0) {
2339 DCHECK(group);
2341 attrib_0_value_.v[0] = 0.0f;
2342 attrib_0_value_.v[1] = 0.0f;
2343 attrib_0_value_.v[2] = 0.0f;
2344 attrib_0_value_.v[3] = 1.0f;
2346 // The shader translator is used for WebGL even when running on EGL
2347 // because additional restrictions are needed (like only enabling
2348 // GL_OES_standard_derivatives on demand). It is used for the unit
2349 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2350 // the empty string to CompileShader and this is not a valid shader.
2351 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2352 CommandLine::ForCurrentProcess()->HasSwitch(
2353 switches::kDisableGLSLTranslator)) {
2354 use_shader_translator_ = false;
2358 GLES2DecoderImpl::~GLES2DecoderImpl() {
2361 bool GLES2DecoderImpl::Initialize(
2362 const scoped_refptr<gfx::GLSurface>& surface,
2363 const scoped_refptr<gfx::GLContext>& context,
2364 bool offscreen,
2365 const gfx::Size& size,
2366 const DisallowedFeatures& disallowed_features,
2367 const std::vector<int32>& attribs) {
2368 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2369 DCHECK(context->IsCurrent(surface.get()));
2370 DCHECK(!context_.get());
2372 set_initialized();
2373 gpu_tracer_.reset(new GPUTracer(this));
2374 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2376 if (CommandLine::ForCurrentProcess()->HasSwitch(
2377 switches::kEnableGPUDebugging)) {
2378 set_debug(true);
2381 if (CommandLine::ForCurrentProcess()->HasSwitch(
2382 switches::kEnableGPUCommandLogging)) {
2383 set_log_commands(true);
2386 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2387 switches::kCompileShaderAlwaysSucceeds);
2390 // Take ownership of the context and surface. The surface can be replaced with
2391 // SetSurface.
2392 context_ = context;
2393 surface_ = surface;
2395 ContextCreationAttribHelper attrib_parser;
2396 if (!attrib_parser.Parse(attribs))
2397 return false;
2399 // Save the loseContextWhenOutOfMemory context creation attribute.
2400 lose_context_when_out_of_memory_ =
2401 attrib_parser.lose_context_when_out_of_memory;
2403 // If the failIfMajorPerformanceCaveat context creation attribute was true
2404 // and we are using a software renderer, fail.
2405 if (attrib_parser.fail_if_major_perf_caveat &&
2406 feature_info_->feature_flags().is_swiftshader) {
2407 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2408 Destroy(true);
2409 return false;
2412 if (!group_->Initialize(this, disallowed_features)) {
2413 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2414 << "failed to initialize.";
2415 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2416 Destroy(true);
2417 return false;
2419 CHECK_GL_ERROR();
2421 disallowed_features_ = disallowed_features;
2423 state_.attrib_values.resize(group_->max_vertex_attribs());
2424 vertex_array_manager_.reset(new VertexArrayManager());
2426 GLuint default_vertex_attrib_service_id = 0;
2427 if (features().native_vertex_array_object) {
2428 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2429 glBindVertexArrayOES(default_vertex_attrib_service_id);
2432 state_.default_vertex_attrib_manager =
2433 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2435 state_.default_vertex_attrib_manager->Initialize(
2436 group_->max_vertex_attribs(),
2437 feature_info_->workarounds().init_vertex_attributes);
2439 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2440 DoBindVertexArrayOES(0);
2442 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2444 image_manager_.reset(new ImageManager);
2446 util_.set_num_compressed_texture_formats(
2447 validators_->compressed_texture_format.GetValues().size());
2449 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2450 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2451 // OpenGL ES 2.0 does not have this issue.
2452 glEnableVertexAttribArray(0);
2454 glGenBuffersARB(1, &attrib_0_buffer_id_);
2455 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2456 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2457 glBindBuffer(GL_ARRAY_BUFFER, 0);
2458 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2460 state_.texture_units.resize(group_->max_texture_units());
2461 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2462 glActiveTexture(GL_TEXTURE0 + tt);
2463 // We want the last bind to be 2D.
2464 TextureRef* ref;
2465 if (features().oes_egl_image_external) {
2466 ref = texture_manager()->GetDefaultTextureInfo(
2467 GL_TEXTURE_EXTERNAL_OES);
2468 state_.texture_units[tt].bound_texture_external_oes = ref;
2469 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2471 if (features().arb_texture_rectangle) {
2472 ref = texture_manager()->GetDefaultTextureInfo(
2473 GL_TEXTURE_RECTANGLE_ARB);
2474 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2475 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2477 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2478 state_.texture_units[tt].bound_texture_cube_map = ref;
2479 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2480 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2481 state_.texture_units[tt].bound_texture_2d = ref;
2482 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2484 glActiveTexture(GL_TEXTURE0);
2485 CHECK_GL_ERROR();
2487 if (offscreen) {
2488 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2489 features().chromium_framebuffer_multisample) {
2490 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2491 // max_sample_count must be initialized to a sane value. If
2492 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2493 GLint max_sample_count = 1;
2494 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2495 offscreen_target_samples_ = std::min(attrib_parser.samples,
2496 max_sample_count);
2497 } else {
2498 offscreen_target_samples_ = 1;
2500 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2502 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2503 const bool rgb8_supported =
2504 context_->HasExtension("GL_OES_rgb8_rgba8");
2505 // The only available default render buffer formats in GLES2 have very
2506 // little precision. Don't enable multisampling unless 8-bit render
2507 // buffer formats are available--instead fall back to 8-bit textures.
2508 if (rgb8_supported && offscreen_target_samples_ > 1) {
2509 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2510 GL_RGBA8 : GL_RGB8;
2511 } else {
2512 offscreen_target_samples_ = 1;
2513 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2514 GL_RGBA : GL_RGB;
2517 // ANGLE only supports packed depth/stencil formats, so use it if it is
2518 // available.
2519 const bool depth24_stencil8_supported =
2520 feature_info_->feature_flags().packed_depth24_stencil8;
2521 VLOG(1) << "GL_OES_packed_depth_stencil "
2522 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2523 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2524 depth24_stencil8_supported) {
2525 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2526 offscreen_target_stencil_format_ = 0;
2527 } else {
2528 // It may be the case that this depth/stencil combination is not
2529 // supported, but this will be checked later by CheckFramebufferStatus.
2530 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2531 GL_DEPTH_COMPONENT16 : 0;
2532 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2533 GL_STENCIL_INDEX8 : 0;
2535 } else {
2536 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2537 GL_RGBA : GL_RGB;
2539 // If depth is requested at all, use the packed depth stencil format if
2540 // it's available, as some desktop GL drivers don't support any non-packed
2541 // formats for depth attachments.
2542 const bool depth24_stencil8_supported =
2543 feature_info_->feature_flags().packed_depth24_stencil8;
2544 VLOG(1) << "GL_EXT_packed_depth_stencil "
2545 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2547 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2548 depth24_stencil8_supported) {
2549 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2550 offscreen_target_stencil_format_ = 0;
2551 } else {
2552 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2553 GL_DEPTH_COMPONENT : 0;
2554 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2555 GL_STENCIL_INDEX : 0;
2559 offscreen_saved_color_format_ = attrib_parser.alpha_size > 0 ?
2560 GL_RGBA : GL_RGB;
2562 // Create the target frame buffer. This is the one that the client renders
2563 // directly to.
2564 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2565 offscreen_target_frame_buffer_->Create();
2566 // Due to GLES2 format limitations, either the color texture (for
2567 // non-multisampling) or the color render buffer (for multisampling) will be
2568 // attached to the offscreen frame buffer. The render buffer has more
2569 // limited formats available to it, but the texture can't do multisampling.
2570 if (IsOffscreenBufferMultisampled()) {
2571 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2572 renderbuffer_manager(), memory_tracker(), &state_));
2573 offscreen_target_color_render_buffer_->Create();
2574 } else {
2575 offscreen_target_color_texture_.reset(new BackTexture(
2576 memory_tracker(), &state_));
2577 offscreen_target_color_texture_->Create();
2579 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2580 renderbuffer_manager(), memory_tracker(), &state_));
2581 offscreen_target_depth_render_buffer_->Create();
2582 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2583 renderbuffer_manager(), memory_tracker(), &state_));
2584 offscreen_target_stencil_render_buffer_->Create();
2586 // Create the saved offscreen texture. The target frame buffer is copied
2587 // here when SwapBuffers is called.
2588 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2589 offscreen_saved_frame_buffer_->Create();
2591 offscreen_saved_color_texture_.reset(new BackTexture(
2592 memory_tracker(), &state_));
2593 offscreen_saved_color_texture_->Create();
2595 // Allocate the render buffers at their initial size and check the status
2596 // of the frame buffers is okay.
2597 if (!ResizeOffscreenFrameBuffer(size)) {
2598 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2599 Destroy(true);
2600 return false;
2603 // Allocate the offscreen saved color texture.
2604 DCHECK(offscreen_saved_color_format_);
2605 offscreen_saved_color_texture_->AllocateStorage(
2606 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2608 offscreen_saved_frame_buffer_->AttachRenderTexture(
2609 offscreen_saved_color_texture_.get());
2610 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2611 GL_FRAMEBUFFER_COMPLETE) {
2612 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2613 Destroy(true);
2614 return false;
2617 // Bind to the new default frame buffer (the offscreen target frame buffer).
2618 // This should now be associated with ID zero.
2619 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2620 } else {
2621 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2622 // These are NOT if the back buffer has these proprorties. They are
2623 // if we want the command buffer to enforce them regardless of what
2624 // the real backbuffer is assuming the real back buffer gives us more than
2625 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2626 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2627 // can't do anything about that.
2629 GLint v = 0;
2630 glGetIntegerv(GL_ALPHA_BITS, &v);
2631 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2632 // user requested RGB then RGB. If the user did not specify a preference
2633 // than use whatever we were given. Same for DEPTH and STENCIL.
2634 back_buffer_color_format_ =
2635 (attrib_parser.alpha_size != 0 && v > 0) ? GL_RGBA : GL_RGB;
2636 glGetIntegerv(GL_DEPTH_BITS, &v);
2637 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && v > 0;
2638 glGetIntegerv(GL_STENCIL_BITS, &v);
2639 back_buffer_has_stencil_ = attrib_parser.stencil_size != 0 && v > 0;
2642 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2643 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2644 // isn't well documented; it was discovered in the Khronos OpenGL ES
2645 // mailing list archives. It also implicitly enables the desktop GL
2646 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2647 // variable in fragment shaders.
2648 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2649 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2650 glEnable(GL_POINT_SPRITE);
2653 has_robustness_extension_ =
2654 context->HasExtension("GL_ARB_robustness") ||
2655 context->HasExtension("GL_EXT_robustness");
2657 if (!InitializeShaderTranslator()) {
2658 return false;
2661 state_.viewport_width = size.width();
2662 state_.viewport_height = size.height();
2664 GLint viewport_params[4] = { 0 };
2665 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2666 viewport_max_width_ = viewport_params[0];
2667 viewport_max_height_ = viewport_params[1];
2669 state_.scissor_width = state_.viewport_width;
2670 state_.scissor_height = state_.viewport_height;
2672 // Set all the default state because some GL drivers get it wrong.
2673 state_.InitCapabilities(NULL);
2674 state_.InitState(NULL);
2675 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2677 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2678 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2679 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2680 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2682 bool call_gl_clear = true;
2683 #if defined(OS_ANDROID)
2684 // Temporary workaround for Android WebView because this clear ignores the
2685 // clip and corrupts that external UI of the App. Not calling glClear is ok
2686 // because the system already clears the buffer before each draw. Proper
2687 // fix might be setting the scissor clip properly before initialize. See
2688 // crbug.com/259023 for details.
2689 call_gl_clear = surface_->GetHandle();
2690 #endif
2691 if (call_gl_clear) {
2692 // Clear the backbuffer.
2693 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2696 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2697 if (feature_info_->workarounds()
2698 .disable_post_sub_buffers_for_onscreen_surfaces &&
2699 !surface->IsOffscreen())
2700 supports_post_sub_buffer_ = false;
2702 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2703 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2706 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2707 context_->SetUnbindFboOnMakeCurrent();
2710 // Only compositor contexts are known to use only the subset of GL
2711 // that can be safely migrated between the iGPU and the dGPU. Mark
2712 // those contexts as safe to forcibly transition between the GPUs.
2713 // http://crbug.com/180876, http://crbug.com/227228
2714 if (!offscreen)
2715 context_->SetSafeToForceGpuSwitch();
2717 async_pixel_transfer_manager_.reset(
2718 AsyncPixelTransferManager::Create(context.get()));
2719 async_pixel_transfer_manager_->Initialize(texture_manager());
2721 framebuffer_manager()->AddObserver(this);
2723 return true;
2726 Capabilities GLES2DecoderImpl::GetCapabilities() {
2727 DCHECK(initialized());
2729 Capabilities caps;
2731 caps.egl_image_external =
2732 feature_info_->feature_flags().oes_egl_image_external;
2733 caps.texture_format_bgra8888 =
2734 feature_info_->feature_flags().ext_texture_format_bgra8888;
2735 caps.texture_format_etc1 =
2736 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2737 caps.texture_format_etc1_npot =
2738 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
2739 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2740 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2741 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2742 caps.discard_framebuffer =
2743 feature_info_->feature_flags().ext_discard_framebuffer;
2744 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2746 #if defined(OS_MACOSX)
2747 // This is unconditionally true on mac, no need to test for it at runtime.
2748 caps.iosurface = true;
2749 #endif
2751 caps.post_sub_buffer = supports_post_sub_buffer_;
2752 caps.map_image = true;
2754 return caps;
2757 void GLES2DecoderImpl::UpdateCapabilities() {
2758 util_.set_num_compressed_texture_formats(
2759 validators_->compressed_texture_format.GetValues().size());
2760 util_.set_num_shader_binary_formats(
2761 validators_->shader_binary_format.GetValues().size());
2764 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2765 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2767 if (!use_shader_translator_) {
2768 return true;
2770 ShBuiltInResources resources;
2771 ShInitBuiltInResources(&resources);
2772 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2773 resources.MaxVertexUniformVectors =
2774 group_->max_vertex_uniform_vectors();
2775 resources.MaxVaryingVectors = group_->max_varying_vectors();
2776 resources.MaxVertexTextureImageUnits =
2777 group_->max_vertex_texture_image_units();
2778 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2779 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2780 resources.MaxFragmentUniformVectors =
2781 group_->max_fragment_uniform_vectors();
2782 resources.MaxDrawBuffers = group_->max_draw_buffers();
2783 resources.MaxExpressionComplexity = 256;
2784 resources.MaxCallStackDepth = 256;
2786 GLint range[2] = { 0, 0 };
2787 GLint precision = 0;
2788 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2789 range, &precision);
2790 resources.FragmentPrecisionHigh =
2791 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2793 if (force_webgl_glsl_validation_) {
2794 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2795 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2796 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2797 if (!draw_buffers_explicitly_enabled_)
2798 resources.MaxDrawBuffers = 1;
2799 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2800 } else {
2801 resources.OES_standard_derivatives =
2802 features().oes_standard_derivatives ? 1 : 0;
2803 resources.ARB_texture_rectangle =
2804 features().arb_texture_rectangle ? 1 : 0;
2805 resources.OES_EGL_image_external =
2806 features().oes_egl_image_external ? 1 : 0;
2807 resources.EXT_draw_buffers =
2808 features().ext_draw_buffers ? 1 : 0;
2809 resources.EXT_frag_depth =
2810 features().ext_frag_depth ? 1 : 0;
2811 resources.EXT_shader_texture_lod =
2812 features().ext_shader_texture_lod ? 1 : 0;
2815 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2816 : SH_GLES2_SPEC;
2817 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2818 resources.HashFunction = &CityHash64;
2819 else
2820 resources.HashFunction = NULL;
2821 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2822 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2823 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2824 int driver_bug_workarounds = 0;
2825 if (workarounds().needs_glsl_built_in_function_emulation)
2826 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2827 if (workarounds().init_gl_position_in_vertex_shader)
2828 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2829 if (workarounds().unfold_short_circuit_as_ternary_operation)
2830 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2831 if (workarounds().init_varyings_without_static_use)
2832 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2833 if (workarounds().unroll_for_loop_with_sampler_array_index)
2834 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2835 if (workarounds().scalarize_vec_and_mat_constructor_args)
2836 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
2837 if (workarounds().regenerate_struct_names)
2838 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
2840 vertex_translator_ = shader_translator_cache()->GetTranslator(
2841 GL_VERTEX_SHADER,
2842 shader_spec,
2843 &resources,
2844 implementation_type,
2845 static_cast<ShCompileOptions>(driver_bug_workarounds));
2846 if (!vertex_translator_.get()) {
2847 LOG(ERROR) << "Could not initialize vertex shader translator.";
2848 Destroy(true);
2849 return false;
2852 fragment_translator_ = shader_translator_cache()->GetTranslator(
2853 GL_FRAGMENT_SHADER,
2854 shader_spec,
2855 &resources,
2856 implementation_type,
2857 static_cast<ShCompileOptions>(driver_bug_workarounds));
2858 if (!fragment_translator_.get()) {
2859 LOG(ERROR) << "Could not initialize fragment shader translator.";
2860 Destroy(true);
2861 return false;
2863 return true;
2866 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2867 for (GLsizei ii = 0; ii < n; ++ii) {
2868 if (GetBuffer(client_ids[ii])) {
2869 return false;
2872 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2873 glGenBuffersARB(n, service_ids.get());
2874 for (GLsizei ii = 0; ii < n; ++ii) {
2875 CreateBuffer(client_ids[ii], service_ids[ii]);
2877 return true;
2880 bool GLES2DecoderImpl::GenFramebuffersHelper(
2881 GLsizei n, const GLuint* client_ids) {
2882 for (GLsizei ii = 0; ii < n; ++ii) {
2883 if (GetFramebuffer(client_ids[ii])) {
2884 return false;
2887 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2888 glGenFramebuffersEXT(n, service_ids.get());
2889 for (GLsizei ii = 0; ii < n; ++ii) {
2890 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2892 return true;
2895 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2896 GLsizei n, const GLuint* client_ids) {
2897 for (GLsizei ii = 0; ii < n; ++ii) {
2898 if (GetRenderbuffer(client_ids[ii])) {
2899 return false;
2902 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2903 glGenRenderbuffersEXT(n, service_ids.get());
2904 for (GLsizei ii = 0; ii < n; ++ii) {
2905 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2907 return true;
2910 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2911 for (GLsizei ii = 0; ii < n; ++ii) {
2912 if (GetTexture(client_ids[ii])) {
2913 return false;
2916 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2917 glGenTextures(n, service_ids.get());
2918 for (GLsizei ii = 0; ii < n; ++ii) {
2919 CreateTexture(client_ids[ii], service_ids[ii]);
2921 return true;
2924 void GLES2DecoderImpl::DeleteBuffersHelper(
2925 GLsizei n, const GLuint* client_ids) {
2926 for (GLsizei ii = 0; ii < n; ++ii) {
2927 Buffer* buffer = GetBuffer(client_ids[ii]);
2928 if (buffer && !buffer->IsDeleted()) {
2929 state_.vertex_attrib_manager->Unbind(buffer);
2930 if (state_.bound_array_buffer.get() == buffer) {
2931 state_.bound_array_buffer = NULL;
2933 RemoveBuffer(client_ids[ii]);
2938 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2939 GLsizei n, const GLuint* client_ids) {
2940 bool supports_separate_framebuffer_binds =
2941 features().chromium_framebuffer_multisample;
2943 for (GLsizei ii = 0; ii < n; ++ii) {
2944 Framebuffer* framebuffer =
2945 GetFramebuffer(client_ids[ii]);
2946 if (framebuffer && !framebuffer->IsDeleted()) {
2947 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2948 framebuffer_state_.bound_draw_framebuffer = NULL;
2949 framebuffer_state_.clear_state_dirty = true;
2950 GLenum target = supports_separate_framebuffer_binds ?
2951 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2952 glBindFramebufferEXT(target, GetBackbufferServiceId());
2954 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2955 framebuffer_state_.bound_read_framebuffer = NULL;
2956 GLenum target = supports_separate_framebuffer_binds ?
2957 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2958 glBindFramebufferEXT(target, GetBackbufferServiceId());
2960 OnFboChanged();
2961 RemoveFramebuffer(client_ids[ii]);
2966 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2967 GLsizei n, const GLuint* client_ids) {
2968 bool supports_separate_framebuffer_binds =
2969 features().chromium_framebuffer_multisample;
2970 for (GLsizei ii = 0; ii < n; ++ii) {
2971 Renderbuffer* renderbuffer =
2972 GetRenderbuffer(client_ids[ii]);
2973 if (renderbuffer && !renderbuffer->IsDeleted()) {
2974 if (state_.bound_renderbuffer.get() == renderbuffer) {
2975 state_.bound_renderbuffer = NULL;
2977 // Unbind from current framebuffers.
2978 if (supports_separate_framebuffer_binds) {
2979 if (framebuffer_state_.bound_read_framebuffer.get()) {
2980 framebuffer_state_.bound_read_framebuffer
2981 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2983 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2984 framebuffer_state_.bound_draw_framebuffer
2985 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2987 } else {
2988 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2989 framebuffer_state_.bound_draw_framebuffer
2990 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2993 framebuffer_state_.clear_state_dirty = true;
2994 RemoveRenderbuffer(client_ids[ii]);
2999 void GLES2DecoderImpl::DeleteTexturesHelper(
3000 GLsizei n, const GLuint* client_ids) {
3001 bool supports_separate_framebuffer_binds =
3002 features().chromium_framebuffer_multisample;
3003 for (GLsizei ii = 0; ii < n; ++ii) {
3004 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3005 if (texture_ref) {
3006 Texture* texture = texture_ref->texture();
3007 if (texture->IsAttachedToFramebuffer()) {
3008 framebuffer_state_.clear_state_dirty = true;
3010 // Unbind texture_ref from texture_ref units.
3011 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3012 state_.texture_units[jj].Unbind(texture_ref);
3014 // Unbind from current framebuffers.
3015 if (supports_separate_framebuffer_binds) {
3016 if (framebuffer_state_.bound_read_framebuffer.get()) {
3017 framebuffer_state_.bound_read_framebuffer
3018 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3020 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3021 framebuffer_state_.bound_draw_framebuffer
3022 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3024 } else {
3025 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3026 framebuffer_state_.bound_draw_framebuffer
3027 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3030 #if defined(OS_MACOSX)
3031 GLuint service_id = texture->service_id();
3032 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3033 ReleaseIOSurfaceForTexture(service_id);
3035 #endif
3036 RemoveTexture(client_ids[ii]);
3041 // } // anonymous namespace
3043 bool GLES2DecoderImpl::MakeCurrent() {
3044 if (!context_.get())
3045 return false;
3047 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
3048 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3050 // Some D3D drivers cannot recover from device lost in the GPU process
3051 // sandbox. Allow a new GPU process to launch.
3052 if (workarounds().exit_on_context_lost) {
3053 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
3054 << " a D3D device in the Chrome GPU process sandbox.";
3055 #if defined(OS_WIN)
3056 base::win::SetShouldCrashOnProcessDetach(false);
3057 #endif
3058 exit(0);
3061 return false;
3064 ProcessFinishedAsyncTransfers();
3066 // Rebind the FBO if it was unbound by the context.
3067 if (workarounds().unbind_fbo_on_context_switch)
3068 RestoreFramebufferBindings();
3070 framebuffer_state_.clear_state_dirty = true;
3072 return true;
3075 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3076 ProcessPendingReadPixels();
3077 if (engine() && query_manager_.get())
3078 query_manager_->ProcessPendingTransferQueries();
3080 // TODO(epenner): Is there a better place to do this?
3081 // This needs to occur before we execute any batch of commands
3082 // from the client, as the client may have recieved an async
3083 // completion while issuing those commands.
3084 // "DidFlushStart" would be ideal if we had such a callback.
3085 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3088 static void RebindCurrentFramebuffer(
3089 GLenum target,
3090 Framebuffer* framebuffer,
3091 GLuint back_buffer_service_id) {
3092 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3094 if (framebuffer_id == 0) {
3095 framebuffer_id = back_buffer_service_id;
3098 glBindFramebufferEXT(target, framebuffer_id);
3101 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3102 framebuffer_state_.clear_state_dirty = true;
3104 if (!features().chromium_framebuffer_multisample) {
3105 RebindCurrentFramebuffer(
3106 GL_FRAMEBUFFER,
3107 framebuffer_state_.bound_draw_framebuffer.get(),
3108 GetBackbufferServiceId());
3109 } else {
3110 RebindCurrentFramebuffer(
3111 GL_READ_FRAMEBUFFER_EXT,
3112 framebuffer_state_.bound_read_framebuffer.get(),
3113 GetBackbufferServiceId());
3114 RebindCurrentFramebuffer(
3115 GL_DRAW_FRAMEBUFFER_EXT,
3116 framebuffer_state_.bound_draw_framebuffer.get(),
3117 GetBackbufferServiceId());
3119 OnFboChanged();
3122 bool GLES2DecoderImpl::CheckFramebufferValid(
3123 Framebuffer* framebuffer,
3124 GLenum target, const char* func_name) {
3125 if (!framebuffer) {
3126 if (backbuffer_needs_clear_bits_) {
3127 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3128 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3129 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3130 glClearStencil(0);
3131 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3132 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3133 glClearDepth(1.0f);
3134 state_.SetDeviceDepthMask(GL_TRUE);
3135 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3136 bool reset_draw_buffer = false;
3137 if ((backbuffer_needs_clear_bits_ | GL_COLOR_BUFFER_BIT) != 0 &&
3138 group_->draw_buffer() == GL_NONE) {
3139 reset_draw_buffer = true;
3140 GLenum buf = GL_BACK;
3141 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3142 buf = GL_COLOR_ATTACHMENT0;
3143 glDrawBuffersARB(1, &buf);
3145 glClear(backbuffer_needs_clear_bits_);
3146 if (reset_draw_buffer) {
3147 GLenum buf = GL_NONE;
3148 glDrawBuffersARB(1, &buf);
3150 backbuffer_needs_clear_bits_ = 0;
3151 RestoreClearState();
3153 return true;
3156 if (framebuffer_manager()->IsComplete(framebuffer)) {
3157 return true;
3160 GLenum completeness = framebuffer->IsPossiblyComplete();
3161 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3162 LOCAL_SET_GL_ERROR(
3163 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3164 return false;
3167 // Are all the attachments cleared?
3168 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3169 texture_manager()->HaveUnclearedMips()) {
3170 if (!framebuffer->IsCleared()) {
3171 // Can we clear them?
3172 if (framebuffer->GetStatus(texture_manager(), target) !=
3173 GL_FRAMEBUFFER_COMPLETE) {
3174 LOCAL_SET_GL_ERROR(
3175 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3176 "framebuffer incomplete (clear)");
3177 return false;
3179 ClearUnclearedAttachments(target, framebuffer);
3183 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3184 if (framebuffer->GetStatus(texture_manager(), target) !=
3185 GL_FRAMEBUFFER_COMPLETE) {
3186 LOCAL_SET_GL_ERROR(
3187 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3188 "framebuffer incomplete (check)");
3189 return false;
3191 framebuffer_manager()->MarkAsComplete(framebuffer);
3194 // NOTE: At this point we don't know if the framebuffer is complete but
3195 // we DO know that everything that needs to be cleared has been cleared.
3196 return true;
3199 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3200 if (!features().chromium_framebuffer_multisample) {
3201 bool valid = CheckFramebufferValid(
3202 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3203 func_name);
3205 if (valid)
3206 OnUseFramebuffer();
3208 return valid;
3210 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3211 GL_DRAW_FRAMEBUFFER_EXT,
3212 func_name) &&
3213 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3214 GL_READ_FRAMEBUFFER_EXT,
3215 func_name);
3218 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3219 const char* func_name) {
3220 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3221 framebuffer_state_.bound_read_framebuffer.get() :
3222 framebuffer_state_.bound_draw_framebuffer.get();
3223 if (!framebuffer)
3224 return true;
3225 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3226 LOCAL_SET_GL_ERROR(
3227 GL_INVALID_OPERATION, func_name, "no color image attached");
3228 return false;
3230 return true;
3233 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3234 Framebuffer* framebuffer =
3235 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3236 if (framebuffer != NULL) {
3237 const Framebuffer::Attachment* attachment =
3238 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3239 if (attachment) {
3240 return gfx::Size(attachment->width(), attachment->height());
3242 return gfx::Size(0, 0);
3243 } else if (offscreen_target_frame_buffer_.get()) {
3244 return offscreen_size_;
3245 } else {
3246 return surface_->GetSize();
3250 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3251 Framebuffer* framebuffer =
3252 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3253 if (framebuffer != NULL) {
3254 return framebuffer->GetColorAttachmentTextureType();
3255 } else {
3256 return GL_UNSIGNED_BYTE;
3260 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3261 Framebuffer* framebuffer =
3262 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3263 if (framebuffer != NULL) {
3264 return framebuffer->GetColorAttachmentFormat();
3265 } else if (offscreen_target_frame_buffer_.get()) {
3266 return offscreen_target_color_format_;
3267 } else {
3268 return back_buffer_color_format_;
3272 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3273 Framebuffer* framebuffer =
3274 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3275 if (framebuffer != NULL) {
3276 return framebuffer->GetColorAttachmentFormat();
3277 } else if (offscreen_target_frame_buffer_.get()) {
3278 return offscreen_target_color_format_;
3279 } else {
3280 return back_buffer_color_format_;
3284 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3285 if (!offscreen_saved_color_texture_info_.get())
3286 return;
3287 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3288 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3289 texture_manager()->SetLevelInfo(
3290 offscreen_saved_color_texture_info_.get(),
3291 GL_TEXTURE_2D,
3292 0, // level
3293 GL_RGBA,
3294 offscreen_size_.width(),
3295 offscreen_size_.height(),
3296 1, // depth
3297 0, // border
3298 GL_RGBA,
3299 GL_UNSIGNED_BYTE,
3300 true);
3301 texture_manager()->SetParameteri(
3302 "UpdateParentTextureInfo",
3303 GetErrorState(),
3304 offscreen_saved_color_texture_info_.get(),
3305 GL_TEXTURE_MAG_FILTER,
3306 GL_LINEAR);
3307 texture_manager()->SetParameteri(
3308 "UpdateParentTextureInfo",
3309 GetErrorState(),
3310 offscreen_saved_color_texture_info_.get(),
3311 GL_TEXTURE_MIN_FILTER,
3312 GL_LINEAR);
3313 texture_manager()->SetParameteri(
3314 "UpdateParentTextureInfo",
3315 GetErrorState(),
3316 offscreen_saved_color_texture_info_.get(),
3317 GL_TEXTURE_WRAP_S,
3318 GL_CLAMP_TO_EDGE);
3319 texture_manager()->SetParameteri(
3320 "UpdateParentTextureInfo",
3321 GetErrorState(),
3322 offscreen_saved_color_texture_info_.get(),
3323 GL_TEXTURE_WRAP_T,
3324 GL_CLAMP_TO_EDGE);
3325 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3326 &state_, target);
3327 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3330 void GLES2DecoderImpl::SetResizeCallback(
3331 const base::Callback<void(gfx::Size, float)>& callback) {
3332 resize_callback_ = callback;
3335 Logger* GLES2DecoderImpl::GetLogger() {
3336 return &logger_;
3339 void GLES2DecoderImpl::BeginDecoding() {
3340 gpu_tracer_->BeginDecoding();
3341 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3342 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3343 (*cb_command_trace_category_ != 0);
3346 void GLES2DecoderImpl::EndDecoding() {
3347 gpu_tracer_->EndDecoding();
3350 ErrorState* GLES2DecoderImpl::GetErrorState() {
3351 return state_.GetErrorState();
3354 void GLES2DecoderImpl::SetShaderCacheCallback(
3355 const ShaderCacheCallback& callback) {
3356 shader_cache_callback_ = callback;
3359 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3360 const WaitSyncPointCallback& callback) {
3361 wait_sync_point_callback_ = callback;
3364 AsyncPixelTransferManager*
3365 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3366 return async_pixel_transfer_manager_.get();
3369 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3370 async_pixel_transfer_manager_.reset();
3373 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3374 AsyncPixelTransferManager* manager) {
3375 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3378 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3379 uint32* service_texture_id) {
3380 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3381 if (texture_ref) {
3382 *service_texture_id = texture_ref->service_id();
3383 return true;
3385 return false;
3388 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3389 return texture_state_.texture_upload_count +
3390 async_pixel_transfer_manager_->GetTextureUploadCount();
3393 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3394 return texture_state_.total_texture_upload_time +
3395 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3398 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3399 return total_processing_commands_time_;
3402 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3403 total_processing_commands_time_ += time;
3406 void GLES2DecoderImpl::Destroy(bool have_context) {
3407 if (!initialized())
3408 return;
3410 DCHECK(!have_context || context_->IsCurrent(NULL));
3412 // Unbind everything.
3413 state_.vertex_attrib_manager = NULL;
3414 state_.default_vertex_attrib_manager = NULL;
3415 state_.texture_units.clear();
3416 state_.bound_array_buffer = NULL;
3417 state_.current_queries.clear();
3418 framebuffer_state_.bound_read_framebuffer = NULL;
3419 framebuffer_state_.bound_draw_framebuffer = NULL;
3420 state_.bound_renderbuffer = NULL;
3422 if (offscreen_saved_color_texture_info_.get()) {
3423 DCHECK(offscreen_target_color_texture_);
3424 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3425 offscreen_saved_color_texture_->id());
3426 offscreen_saved_color_texture_->Invalidate();
3427 offscreen_saved_color_texture_info_ = NULL;
3429 if (have_context) {
3430 if (copy_texture_CHROMIUM_.get()) {
3431 copy_texture_CHROMIUM_->Destroy();
3432 copy_texture_CHROMIUM_.reset();
3435 if (state_.current_program.get()) {
3436 program_manager()->UnuseProgram(shader_manager(),
3437 state_.current_program.get());
3440 if (attrib_0_buffer_id_) {
3441 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3443 if (fixed_attrib_buffer_id_) {
3444 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3447 if (validation_texture_) {
3448 glDeleteTextures(1, &validation_texture_);
3449 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3450 glDeleteFramebuffersEXT(1, &validation_fbo_);
3453 if (offscreen_target_frame_buffer_.get())
3454 offscreen_target_frame_buffer_->Destroy();
3455 if (offscreen_target_color_texture_.get())
3456 offscreen_target_color_texture_->Destroy();
3457 if (offscreen_target_color_render_buffer_.get())
3458 offscreen_target_color_render_buffer_->Destroy();
3459 if (offscreen_target_depth_render_buffer_.get())
3460 offscreen_target_depth_render_buffer_->Destroy();
3461 if (offscreen_target_stencil_render_buffer_.get())
3462 offscreen_target_stencil_render_buffer_->Destroy();
3463 if (offscreen_saved_frame_buffer_.get())
3464 offscreen_saved_frame_buffer_->Destroy();
3465 if (offscreen_saved_color_texture_.get())
3466 offscreen_saved_color_texture_->Destroy();
3467 if (offscreen_resolved_frame_buffer_.get())
3468 offscreen_resolved_frame_buffer_->Destroy();
3469 if (offscreen_resolved_color_texture_.get())
3470 offscreen_resolved_color_texture_->Destroy();
3471 } else {
3472 if (offscreen_target_frame_buffer_.get())
3473 offscreen_target_frame_buffer_->Invalidate();
3474 if (offscreen_target_color_texture_.get())
3475 offscreen_target_color_texture_->Invalidate();
3476 if (offscreen_target_color_render_buffer_.get())
3477 offscreen_target_color_render_buffer_->Invalidate();
3478 if (offscreen_target_depth_render_buffer_.get())
3479 offscreen_target_depth_render_buffer_->Invalidate();
3480 if (offscreen_target_stencil_render_buffer_.get())
3481 offscreen_target_stencil_render_buffer_->Invalidate();
3482 if (offscreen_saved_frame_buffer_.get())
3483 offscreen_saved_frame_buffer_->Invalidate();
3484 if (offscreen_saved_color_texture_.get())
3485 offscreen_saved_color_texture_->Invalidate();
3486 if (offscreen_resolved_frame_buffer_.get())
3487 offscreen_resolved_frame_buffer_->Invalidate();
3488 if (offscreen_resolved_color_texture_.get())
3489 offscreen_resolved_color_texture_->Invalidate();
3492 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3493 // Otherwise, we can leak objects. http://crbug.com/258772.
3494 // state_.current_program must be reset before group_ is reset because
3495 // the later deletes the ProgramManager object that referred by
3496 // state_.current_program object.
3497 state_.current_program = NULL;
3499 copy_texture_CHROMIUM_.reset();
3501 if (query_manager_.get()) {
3502 query_manager_->Destroy(have_context);
3503 query_manager_.reset();
3506 if (vertex_array_manager_ .get()) {
3507 vertex_array_manager_->Destroy(have_context);
3508 vertex_array_manager_.reset();
3511 if (image_manager_.get()) {
3512 image_manager_->Destroy(have_context);
3513 image_manager_.reset();
3516 offscreen_target_frame_buffer_.reset();
3517 offscreen_target_color_texture_.reset();
3518 offscreen_target_color_render_buffer_.reset();
3519 offscreen_target_depth_render_buffer_.reset();
3520 offscreen_target_stencil_render_buffer_.reset();
3521 offscreen_saved_frame_buffer_.reset();
3522 offscreen_saved_color_texture_.reset();
3523 offscreen_resolved_frame_buffer_.reset();
3524 offscreen_resolved_color_texture_.reset();
3526 // Need to release these before releasing |group_| which may own the
3527 // ShaderTranslatorCache.
3528 fragment_translator_ = NULL;
3529 vertex_translator_ = NULL;
3531 // Should destroy the transfer manager before the texture manager held
3532 // by the context group.
3533 async_pixel_transfer_manager_.reset();
3535 if (group_.get()) {
3536 framebuffer_manager()->RemoveObserver(this);
3537 group_->Destroy(this, have_context);
3538 group_ = NULL;
3541 if (context_.get()) {
3542 context_->ReleaseCurrent(NULL);
3543 context_ = NULL;
3546 #if defined(OS_MACOSX)
3547 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3548 it != texture_to_io_surface_map_.end(); ++it) {
3549 CFRelease(it->second);
3551 texture_to_io_surface_map_.clear();
3552 #endif
3555 void GLES2DecoderImpl::SetSurface(
3556 const scoped_refptr<gfx::GLSurface>& surface) {
3557 DCHECK(context_->IsCurrent(NULL));
3558 DCHECK(surface_.get());
3559 surface_ = surface;
3560 RestoreCurrentFramebufferBindings();
3563 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3564 if (!offscreen_saved_color_texture_.get()) {
3565 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3566 return;
3568 if (!offscreen_saved_color_texture_info_.get()) {
3569 GLuint service_id = offscreen_saved_color_texture_->id();
3570 offscreen_saved_color_texture_info_ = TextureRef::Create(
3571 texture_manager(), 0, service_id);
3572 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3573 GL_TEXTURE_2D);
3574 UpdateParentTextureInfo();
3576 mailbox_manager()->ProduceTexture(
3577 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3580 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3581 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3582 if (!is_offscreen) {
3583 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3584 << " with an onscreen framebuffer.";
3585 return false;
3588 if (offscreen_size_ == size)
3589 return true;
3591 offscreen_size_ = size;
3592 int w = offscreen_size_.width();
3593 int h = offscreen_size_.height();
3594 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3595 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3596 << "to allocate storage due to excessive dimensions.";
3597 return false;
3600 // Reallocate the offscreen target buffers.
3601 DCHECK(offscreen_target_color_format_);
3602 if (IsOffscreenBufferMultisampled()) {
3603 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3604 feature_info_.get(),
3605 offscreen_size_,
3606 offscreen_target_color_format_,
3607 offscreen_target_samples_)) {
3608 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3609 << "to allocate storage for offscreen target color buffer.";
3610 return false;
3612 } else {
3613 if (!offscreen_target_color_texture_->AllocateStorage(
3614 offscreen_size_, offscreen_target_color_format_, false)) {
3615 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3616 << "to allocate storage for offscreen target color texture.";
3617 return false;
3620 if (offscreen_target_depth_format_ &&
3621 !offscreen_target_depth_render_buffer_->AllocateStorage(
3622 feature_info_.get(),
3623 offscreen_size_,
3624 offscreen_target_depth_format_,
3625 offscreen_target_samples_)) {
3626 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3627 << "to allocate storage for offscreen target depth buffer.";
3628 return false;
3630 if (offscreen_target_stencil_format_ &&
3631 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3632 feature_info_.get(),
3633 offscreen_size_,
3634 offscreen_target_stencil_format_,
3635 offscreen_target_samples_)) {
3636 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3637 << "to allocate storage for offscreen target stencil buffer.";
3638 return false;
3641 // Attach the offscreen target buffers to the target frame buffer.
3642 if (IsOffscreenBufferMultisampled()) {
3643 offscreen_target_frame_buffer_->AttachRenderBuffer(
3644 GL_COLOR_ATTACHMENT0,
3645 offscreen_target_color_render_buffer_.get());
3646 } else {
3647 offscreen_target_frame_buffer_->AttachRenderTexture(
3648 offscreen_target_color_texture_.get());
3650 if (offscreen_target_depth_format_) {
3651 offscreen_target_frame_buffer_->AttachRenderBuffer(
3652 GL_DEPTH_ATTACHMENT,
3653 offscreen_target_depth_render_buffer_.get());
3655 const bool packed_depth_stencil =
3656 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3657 if (packed_depth_stencil) {
3658 offscreen_target_frame_buffer_->AttachRenderBuffer(
3659 GL_STENCIL_ATTACHMENT,
3660 offscreen_target_depth_render_buffer_.get());
3661 } else if (offscreen_target_stencil_format_) {
3662 offscreen_target_frame_buffer_->AttachRenderBuffer(
3663 GL_STENCIL_ATTACHMENT,
3664 offscreen_target_stencil_render_buffer_.get());
3667 if (offscreen_target_frame_buffer_->CheckStatus() !=
3668 GL_FRAMEBUFFER_COMPLETE) {
3669 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3670 << "because offscreen FBO was incomplete.";
3671 return false;
3674 // Clear the target frame buffer.
3676 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3677 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3678 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3679 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3680 glClearStencil(0);
3681 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3682 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3683 glClearDepth(0);
3684 state_.SetDeviceDepthMask(GL_TRUE);
3685 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3686 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3687 RestoreClearState();
3690 // Destroy the offscreen resolved framebuffers.
3691 if (offscreen_resolved_frame_buffer_.get())
3692 offscreen_resolved_frame_buffer_->Destroy();
3693 if (offscreen_resolved_color_texture_.get())
3694 offscreen_resolved_color_texture_->Destroy();
3695 offscreen_resolved_color_texture_.reset();
3696 offscreen_resolved_frame_buffer_.reset();
3698 return true;
3701 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
3702 const void* cmd_data) {
3703 const gles2::cmds::ResizeCHROMIUM& c =
3704 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
3705 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3706 return error::kDeferCommandUntilLater;
3708 GLuint width = static_cast<GLuint>(c.width);
3709 GLuint height = static_cast<GLuint>(c.height);
3710 GLfloat scale_factor = c.scale_factor;
3711 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3713 width = std::max(1U, width);
3714 height = std::max(1U, height);
3716 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3717 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3718 // Make sure that we are done drawing to the back buffer before resizing.
3719 glFinish();
3720 #endif
3721 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3722 if (is_offscreen) {
3723 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3724 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3725 << "ResizeOffscreenFrameBuffer failed.";
3726 return error::kLostContext;
3730 if (!resize_callback_.is_null()) {
3731 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3732 DCHECK(context_->IsCurrent(surface_.get()));
3733 if (!context_->IsCurrent(surface_.get())) {
3734 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3735 << "current after resize callback.";
3736 return error::kLostContext;
3740 return error::kNoError;
3743 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3744 if (command_id > kStartPoint && command_id < kNumCommands) {
3745 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3747 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3750 // Decode a command, and call the corresponding GL functions.
3751 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
3752 // of commands at once, and is now only used for tests that need to track
3753 // individual commands.
3754 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
3755 unsigned int arg_count,
3756 const void* cmd_data) {
3757 return DoCommands(1, cmd_data, arg_count + 1, 0);
3760 // Decode multiple commands, and call the corresponding GL functions.
3761 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
3762 // changed by a (malicious) client at any time, so if validation has to happen,
3763 // it should operate on a copy of them.
3764 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
3765 // interest of performance in this critical execution loop.
3766 template <bool DebugImpl>
3767 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
3768 const void* buffer,
3769 int num_entries,
3770 int* entries_processed) {
3771 commands_to_process_ = num_commands;
3772 error::Error result = error::kNoError;
3773 const CommandBufferEntry* cmd_data =
3774 static_cast<const CommandBufferEntry*>(buffer);
3775 int process_pos = 0;
3776 unsigned int command = 0;
3778 while (process_pos < num_entries && result == error::kNoError &&
3779 commands_to_process_--) {
3780 const unsigned int size = cmd_data->value_header.size;
3781 command = cmd_data->value_header.command;
3783 if (size == 0) {
3784 result = error::kInvalidSize;
3785 break;
3788 if (static_cast<int>(size) + process_pos > num_entries) {
3789 result = error::kOutOfBounds;
3790 break;
3793 if (DebugImpl) {
3794 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3795 GetCommandName(command));
3797 if (log_commands()) {
3798 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
3799 << "cmd: " << GetCommandName(command);
3803 const unsigned int arg_count = size - 1;
3804 unsigned int command_index = command - kStartPoint - 1;
3805 if (command_index < arraysize(command_info)) {
3806 const CommandInfo& info = command_info[command_index];
3807 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3808 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3809 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3810 bool doing_gpu_trace = false;
3811 if (DebugImpl && gpu_trace_commands_) {
3812 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3813 doing_gpu_trace = true;
3814 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3818 uint32 immediate_data_size = (arg_count - info_arg_count) *
3819 sizeof(CommandBufferEntry); // NOLINT
3821 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
3823 if (DebugImpl && doing_gpu_trace)
3824 gpu_tracer_->End(kTraceDecoder);
3826 if (DebugImpl && debug()) {
3827 GLenum error;
3828 while ((error = glGetError()) != GL_NO_ERROR) {
3829 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3830 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
3831 << " : " << GetCommandName(command);
3832 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3835 } else {
3836 result = error::kInvalidArguments;
3838 } else {
3839 result = DoCommonCommand(command, arg_count, cmd_data);
3842 if (DebugImpl) {
3843 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3844 GetCommandName(command));
3847 if (result == error::kNoError &&
3848 current_decoder_error_ != error::kNoError) {
3849 result = current_decoder_error_;
3850 current_decoder_error_ = error::kNoError;
3853 if (result != error::kDeferCommandUntilLater) {
3854 process_pos += size;
3855 cmd_data += size;
3859 if (entries_processed)
3860 *entries_processed = process_pos;
3862 if (error::IsError(result)) {
3863 LOG(ERROR) << "Error: " << result << " for Command "
3864 << GetCommandName(command);
3867 return result;
3870 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
3871 const void* buffer,
3872 int num_entries,
3873 int* entries_processed) {
3874 if (gpu_debug_commands_) {
3875 return DoCommandsImpl<true>(
3876 num_commands, buffer, num_entries, entries_processed);
3877 } else {
3878 return DoCommandsImpl<false>(
3879 num_commands, buffer, num_entries, entries_processed);
3883 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3884 buffer_manager()->RemoveBuffer(client_id);
3887 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3888 if (GetProgram(client_id)) {
3889 return false;
3891 GLuint service_id = glCreateProgram();
3892 if (service_id != 0) {
3893 CreateProgram(client_id, service_id);
3895 return true;
3898 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3899 if (GetShader(client_id)) {
3900 return false;
3902 GLuint service_id = glCreateShader(type);
3903 if (service_id != 0) {
3904 CreateShader(client_id, service_id, type);
3906 return true;
3909 void GLES2DecoderImpl::DoFinish() {
3910 glFinish();
3911 ProcessPendingReadPixels();
3912 ProcessPendingQueries();
3915 void GLES2DecoderImpl::DoFlush() {
3916 glFlush();
3917 ProcessPendingQueries();
3920 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3921 GLuint texture_index = texture_unit - GL_TEXTURE0;
3922 if (texture_index >= state_.texture_units.size()) {
3923 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3924 "glActiveTexture", texture_unit, "texture_unit");
3925 return;
3927 state_.active_texture_unit = texture_index;
3928 glActiveTexture(texture_unit);
3931 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3932 Buffer* buffer = NULL;
3933 GLuint service_id = 0;
3934 if (client_id != 0) {
3935 buffer = GetBuffer(client_id);
3936 if (!buffer) {
3937 if (!group_->bind_generates_resource()) {
3938 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3939 "glBindBuffer",
3940 "id not generated by glGenBuffers");
3941 return;
3944 // It's a new id so make a buffer buffer for it.
3945 glGenBuffersARB(1, &service_id);
3946 CreateBuffer(client_id, service_id);
3947 buffer = GetBuffer(client_id);
3948 IdAllocatorInterface* id_allocator =
3949 group_->GetIdAllocator(id_namespaces::kBuffers);
3950 id_allocator->MarkAsUsed(client_id);
3953 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3954 if (buffer) {
3955 if (!buffer_manager()->SetTarget(buffer, target)) {
3956 LOCAL_SET_GL_ERROR(
3957 GL_INVALID_OPERATION,
3958 "glBindBuffer", "buffer bound to more than 1 target");
3959 return;
3961 service_id = buffer->service_id();
3963 switch (target) {
3964 case GL_ARRAY_BUFFER:
3965 state_.bound_array_buffer = buffer;
3966 break;
3967 case GL_ELEMENT_ARRAY_BUFFER:
3968 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3969 break;
3970 default:
3971 NOTREACHED(); // Validation should prevent us getting here.
3972 break;
3974 glBindBuffer(target, service_id);
3977 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3978 bool all_draw_buffers) {
3979 Framebuffer* framebuffer =
3980 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3981 if (!all_draw_buffers || !framebuffer) {
3982 return (GLES2Util::GetChannelsForFormat(
3983 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3985 return framebuffer->HasAlphaMRT();
3988 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3989 Framebuffer* framebuffer =
3990 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3991 if (framebuffer) {
3992 return framebuffer->HasDepthAttachment();
3994 if (offscreen_target_frame_buffer_.get()) {
3995 return offscreen_target_depth_format_ != 0;
3997 return back_buffer_has_depth_;
4000 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4001 Framebuffer* framebuffer =
4002 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4003 if (framebuffer) {
4004 return framebuffer->HasStencilAttachment();
4006 if (offscreen_target_frame_buffer_.get()) {
4007 return offscreen_target_stencil_format_ != 0 ||
4008 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4010 return back_buffer_has_stencil_;
4013 void GLES2DecoderImpl::ApplyDirtyState() {
4014 if (framebuffer_state_.clear_state_dirty) {
4015 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4016 state_.SetDeviceColorMask(state_.color_mask_red,
4017 state_.color_mask_green,
4018 state_.color_mask_blue,
4019 state_.color_mask_alpha && have_alpha);
4021 bool have_depth = BoundFramebufferHasDepthAttachment();
4022 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4024 bool have_stencil = BoundFramebufferHasStencilAttachment();
4025 state_.SetDeviceStencilMaskSeparate(
4026 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4027 state_.SetDeviceStencilMaskSeparate(
4028 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4030 state_.SetDeviceCapabilityState(
4031 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4032 state_.SetDeviceCapabilityState(
4033 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4034 framebuffer_state_.clear_state_dirty = false;
4038 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4039 return (offscreen_target_frame_buffer_.get())
4040 ? offscreen_target_frame_buffer_->id()
4041 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4044 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4045 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4046 "context", logger_.GetLogPrefix());
4047 // Restore the Framebuffer first because of bugs in Intel drivers.
4048 // Intel drivers incorrectly clip the viewport settings to
4049 // the size of the current framebuffer object.
4050 RestoreFramebufferBindings();
4051 state_.RestoreState(prev_state);
4054 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4055 GLuint service_id =
4056 framebuffer_state_.bound_draw_framebuffer.get()
4057 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4058 : GetBackbufferServiceId();
4059 if (!features().chromium_framebuffer_multisample) {
4060 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4061 } else {
4062 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4063 service_id = framebuffer_state_.bound_read_framebuffer.get()
4064 ? framebuffer_state_.bound_read_framebuffer->service_id()
4065 : GetBackbufferServiceId();
4066 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4068 OnFboChanged();
4071 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4072 state_.RestoreRenderbufferBindings();
4075 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4076 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4077 if (texture) {
4078 GLenum target = texture->target();
4079 glBindTexture(target, service_id);
4080 glTexParameteri(
4081 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4082 glTexParameteri(
4083 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4084 glTexParameteri(
4085 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4086 glTexParameteri(
4087 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4088 RestoreTextureUnitBindings(state_.active_texture_unit);
4092 void GLES2DecoderImpl::ClearAllAttributes() const {
4093 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4094 // other VAOs.
4095 if (feature_info_->feature_flags().native_vertex_array_object)
4096 glBindVertexArrayOES(0);
4098 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4099 if (i != 0) // Never disable attribute 0
4100 glDisableVertexAttribArray(i);
4101 if(features().angle_instanced_arrays)
4102 glVertexAttribDivisorANGLE(i, 0);
4106 void GLES2DecoderImpl::RestoreAllAttributes() const {
4107 state_.RestoreVertexAttribs();
4110 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4111 state_.SetIgnoreCachedStateForTest(ignore);
4114 void GLES2DecoderImpl::OnFboChanged() const {
4115 if (workarounds().restore_scissor_on_fbo_change)
4116 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
4119 // Called after the FBO is checked for completeness.
4120 void GLES2DecoderImpl::OnUseFramebuffer() const {
4121 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
4122 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
4123 // The driver forgets the correct scissor when modifying the FBO binding.
4124 glScissor(state_.scissor_x,
4125 state_.scissor_y,
4126 state_.scissor_width,
4127 state_.scissor_height);
4129 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4130 // it's unclear how this bug works.
4131 glFlush();
4135 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4136 Framebuffer* framebuffer = NULL;
4137 GLuint service_id = 0;
4138 if (client_id != 0) {
4139 framebuffer = GetFramebuffer(client_id);
4140 if (!framebuffer) {
4141 if (!group_->bind_generates_resource()) {
4142 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4143 "glBindFramebuffer",
4144 "id not generated by glGenFramebuffers");
4145 return;
4148 // It's a new id so make a framebuffer framebuffer for it.
4149 glGenFramebuffersEXT(1, &service_id);
4150 CreateFramebuffer(client_id, service_id);
4151 framebuffer = GetFramebuffer(client_id);
4152 IdAllocatorInterface* id_allocator =
4153 group_->GetIdAllocator(id_namespaces::kFramebuffers);
4154 id_allocator->MarkAsUsed(client_id);
4155 } else {
4156 service_id = framebuffer->service_id();
4158 framebuffer->MarkAsValid();
4160 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4162 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4163 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4166 // vmiura: This looks like dup code
4167 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4168 framebuffer_state_.bound_read_framebuffer = framebuffer;
4171 framebuffer_state_.clear_state_dirty = true;
4173 // If we are rendering to the backbuffer get the FBO id for any simulated
4174 // backbuffer.
4175 if (framebuffer == NULL) {
4176 service_id = GetBackbufferServiceId();
4179 glBindFramebufferEXT(target, service_id);
4180 OnFboChanged();
4183 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4184 Renderbuffer* renderbuffer = NULL;
4185 GLuint service_id = 0;
4186 if (client_id != 0) {
4187 renderbuffer = GetRenderbuffer(client_id);
4188 if (!renderbuffer) {
4189 if (!group_->bind_generates_resource()) {
4190 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4191 "glBindRenderbuffer",
4192 "id not generated by glGenRenderbuffers");
4193 return;
4196 // It's a new id so make a renderbuffer for it.
4197 glGenRenderbuffersEXT(1, &service_id);
4198 CreateRenderbuffer(client_id, service_id);
4199 renderbuffer = GetRenderbuffer(client_id);
4200 IdAllocatorInterface* id_allocator =
4201 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
4202 id_allocator->MarkAsUsed(client_id);
4203 } else {
4204 service_id = renderbuffer->service_id();
4206 renderbuffer->MarkAsValid();
4208 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4209 state_.bound_renderbuffer = renderbuffer;
4210 state_.bound_renderbuffer_valid = true;
4211 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4214 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4215 TextureRef* texture_ref = NULL;
4216 GLuint service_id = 0;
4217 if (client_id != 0) {
4218 texture_ref = GetTexture(client_id);
4219 if (!texture_ref) {
4220 if (!group_->bind_generates_resource()) {
4221 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4222 "glBindTexture",
4223 "id not generated by glGenTextures");
4224 return;
4227 // It's a new id so make a texture texture for it.
4228 glGenTextures(1, &service_id);
4229 DCHECK_NE(0u, service_id);
4230 CreateTexture(client_id, service_id);
4231 texture_ref = GetTexture(client_id);
4232 IdAllocatorInterface* id_allocator =
4233 group_->GetIdAllocator(id_namespaces::kTextures);
4234 id_allocator->MarkAsUsed(client_id);
4236 } else {
4237 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4240 // Check the texture exists
4241 if (texture_ref) {
4242 Texture* texture = texture_ref->texture();
4243 // Check that we are not trying to bind it to a different target.
4244 if (texture->target() != 0 && texture->target() != target) {
4245 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4246 "glBindTexture",
4247 "texture bound to more than 1 target.");
4248 return;
4250 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4251 if (texture->target() == 0) {
4252 texture_manager()->SetTarget(texture_ref, target);
4254 glBindTexture(target, texture->service_id());
4255 } else {
4256 glBindTexture(target, 0);
4259 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4260 unit.bind_target = target;
4261 switch (target) {
4262 case GL_TEXTURE_2D:
4263 unit.bound_texture_2d = texture_ref;
4264 break;
4265 case GL_TEXTURE_CUBE_MAP:
4266 unit.bound_texture_cube_map = texture_ref;
4267 break;
4268 case GL_TEXTURE_EXTERNAL_OES:
4269 unit.bound_texture_external_oes = texture_ref;
4270 break;
4271 case GL_TEXTURE_RECTANGLE_ARB:
4272 unit.bound_texture_rectangle_arb = texture_ref;
4273 break;
4274 default:
4275 NOTREACHED(); // Validation should prevent us getting here.
4276 break;
4280 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4281 if (state_.vertex_attrib_manager->Enable(index, false)) {
4282 if (index != 0 ||
4283 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4284 glDisableVertexAttribArray(index);
4286 } else {
4287 LOCAL_SET_GL_ERROR(
4288 GL_INVALID_VALUE,
4289 "glDisableVertexAttribArray", "index out of range");
4293 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4294 GLsizei numAttachments,
4295 const GLenum* attachments) {
4296 Framebuffer* framebuffer =
4297 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4299 // Validates the attachments. If one of them fails
4300 // the whole command fails.
4301 for (GLsizei i = 0; i < numAttachments; ++i) {
4302 if ((framebuffer &&
4303 !validators_->attachment.IsValid(attachments[i])) ||
4304 (!framebuffer &&
4305 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4306 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4307 "glDiscardFramebufferEXT", attachments[i], "attachments");
4308 return;
4312 // Marks each one of them as not cleared
4313 for (GLsizei i = 0; i < numAttachments; ++i) {
4314 if (framebuffer) {
4315 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4316 texture_manager(),
4317 attachments[i],
4318 false);
4319 } else {
4320 switch (attachments[i]) {
4321 case GL_COLOR_EXT:
4322 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4323 break;
4324 case GL_DEPTH_EXT:
4325 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4326 case GL_STENCIL_EXT:
4327 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4328 break;
4329 default:
4330 NOTREACHED();
4331 break;
4336 // If the default framebuffer is bound but we are still rendering to an
4337 // FBO, translate attachment names that refer to default framebuffer
4338 // channels to corresponding framebuffer attachments.
4339 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4340 for (GLsizei i = 0; i < numAttachments; ++i) {
4341 GLenum attachment = attachments[i];
4342 if (!framebuffer && GetBackbufferServiceId()) {
4343 switch (attachment) {
4344 case GL_COLOR_EXT:
4345 attachment = GL_COLOR_ATTACHMENT0;
4346 break;
4347 case GL_DEPTH_EXT:
4348 attachment = GL_DEPTH_ATTACHMENT;
4349 break;
4350 case GL_STENCIL_EXT:
4351 attachment = GL_STENCIL_ATTACHMENT;
4352 break;
4353 default:
4354 NOTREACHED();
4355 return;
4358 translated_attachments[i] = attachment;
4361 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4364 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4365 if (state_.vertex_attrib_manager->Enable(index, true)) {
4366 glEnableVertexAttribArray(index);
4367 } else {
4368 LOCAL_SET_GL_ERROR(
4369 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4373 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4374 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4375 &state_, target);
4376 if (!texture_ref ||
4377 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4378 LOCAL_SET_GL_ERROR(
4379 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4380 return;
4383 if (target == GL_TEXTURE_CUBE_MAP) {
4384 for (int i = 0; i < 6; ++i) {
4385 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4386 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4387 LOCAL_SET_GL_ERROR(
4388 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4389 return;
4392 } else {
4393 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4394 LOCAL_SET_GL_ERROR(
4395 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4396 return;
4400 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4401 // Workaround for Mac driver bug. In the large scheme of things setting
4402 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4403 // hit so there's probably no need to make this conditional. The bug appears
4404 // to be that if the filtering mode is set to something that doesn't require
4405 // mipmaps for rendering, or is never set to something other than the default,
4406 // then glGenerateMipmap misbehaves.
4407 if (workarounds().set_texture_filter_before_generating_mipmap) {
4408 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4410 glGenerateMipmapEXT(target);
4411 if (workarounds().set_texture_filter_before_generating_mipmap) {
4412 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4413 texture_ref->texture()->min_filter());
4415 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4416 if (error == GL_NO_ERROR) {
4417 texture_manager()->MarkMipmapsGenerated(texture_ref);
4421 bool GLES2DecoderImpl::GetHelper(
4422 GLenum pname, GLint* params, GLsizei* num_written) {
4423 DCHECK(num_written);
4424 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4425 switch (pname) {
4426 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4427 *num_written = 1;
4428 // Return the GL implementation's preferred format and (see below type)
4429 // if we have the GL extension that exposes this. This allows the GPU
4430 // client to use the implementation's preferred format for glReadPixels
4431 // for optimisation.
4433 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4434 // case when requested on integer/floating point buffers but which is
4435 // acceptable on GLES2 and with the GL_OES_read_format extension.
4437 // Therefore if an error occurs we swallow the error and use the
4438 // internal implementation.
4439 if (params) {
4440 if (context_->HasExtension("GL_OES_read_format")) {
4441 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4442 GetErrorState());
4443 glGetIntegerv(pname, params);
4444 if (glGetError() == GL_NO_ERROR)
4445 return true;
4447 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4448 GetBoundReadFrameBufferInternalFormat());
4450 return true;
4451 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4452 *num_written = 1;
4453 if (params) {
4454 if (context_->HasExtension("GL_OES_read_format")) {
4455 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4456 GetErrorState());
4457 glGetIntegerv(pname, params);
4458 if (glGetError() == GL_NO_ERROR)
4459 return true;
4461 *params = GLES2Util::GetPreferredGLReadPixelsType(
4462 GetBoundReadFrameBufferInternalFormat(),
4463 GetBoundReadFrameBufferTextureType());
4465 return true;
4466 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4467 *num_written = 1;
4468 if (params) {
4469 *params = group_->max_fragment_uniform_vectors();
4471 return true;
4472 case GL_MAX_VARYING_VECTORS:
4473 *num_written = 1;
4474 if (params) {
4475 *params = group_->max_varying_vectors();
4477 return true;
4478 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4479 *num_written = 1;
4480 if (params) {
4481 *params = group_->max_vertex_uniform_vectors();
4483 return true;
4486 switch (pname) {
4487 case GL_MAX_VIEWPORT_DIMS:
4488 if (offscreen_target_frame_buffer_.get()) {
4489 *num_written = 2;
4490 if (params) {
4491 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4492 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4494 return true;
4496 return false;
4497 case GL_MAX_SAMPLES:
4498 *num_written = 1;
4499 if (params) {
4500 params[0] = renderbuffer_manager()->max_samples();
4502 return true;
4503 case GL_MAX_RENDERBUFFER_SIZE:
4504 *num_written = 1;
4505 if (params) {
4506 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4508 return true;
4509 case GL_MAX_TEXTURE_SIZE:
4510 *num_written = 1;
4511 if (params) {
4512 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4514 return true;
4515 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4516 *num_written = 1;
4517 if (params) {
4518 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4520 return true;
4521 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4522 *num_written = 1;
4523 if (params) {
4524 params[0] = group_->max_color_attachments();
4526 return true;
4527 case GL_MAX_DRAW_BUFFERS_ARB:
4528 *num_written = 1;
4529 if (params) {
4530 params[0] = group_->max_draw_buffers();
4532 return true;
4533 case GL_ALPHA_BITS:
4534 *num_written = 1;
4535 if (params) {
4536 GLint v = 0;
4537 glGetIntegerv(GL_ALPHA_BITS, &v);
4538 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4540 return true;
4541 case GL_DEPTH_BITS:
4542 *num_written = 1;
4543 if (params) {
4544 GLint v = 0;
4545 glGetIntegerv(GL_DEPTH_BITS, &v);
4546 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4548 return true;
4549 case GL_STENCIL_BITS:
4550 *num_written = 1;
4551 if (params) {
4552 GLint v = 0;
4553 glGetIntegerv(GL_STENCIL_BITS, &v);
4554 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4556 return true;
4557 case GL_COMPRESSED_TEXTURE_FORMATS:
4558 *num_written = validators_->compressed_texture_format.GetValues().size();
4559 if (params) {
4560 for (GLint ii = 0; ii < *num_written; ++ii) {
4561 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4564 return true;
4565 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4566 *num_written = 1;
4567 if (params) {
4568 *params = validators_->compressed_texture_format.GetValues().size();
4570 return true;
4571 case GL_NUM_SHADER_BINARY_FORMATS:
4572 *num_written = 1;
4573 if (params) {
4574 *params = validators_->shader_binary_format.GetValues().size();
4576 return true;
4577 case GL_SHADER_BINARY_FORMATS:
4578 *num_written = validators_->shader_binary_format.GetValues().size();
4579 if (params) {
4580 for (GLint ii = 0; ii < *num_written; ++ii) {
4581 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4584 return true;
4585 case GL_SHADER_COMPILER:
4586 *num_written = 1;
4587 if (params) {
4588 *params = GL_TRUE;
4590 return true;
4591 case GL_ARRAY_BUFFER_BINDING:
4592 *num_written = 1;
4593 if (params) {
4594 if (state_.bound_array_buffer.get()) {
4595 GLuint client_id = 0;
4596 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4597 &client_id);
4598 *params = client_id;
4599 } else {
4600 *params = 0;
4603 return true;
4604 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4605 *num_written = 1;
4606 if (params) {
4607 if (state_.vertex_attrib_manager->element_array_buffer()) {
4608 GLuint client_id = 0;
4609 buffer_manager()->GetClientId(
4610 state_.vertex_attrib_manager->element_array_buffer()->
4611 service_id(), &client_id);
4612 *params = client_id;
4613 } else {
4614 *params = 0;
4617 return true;
4618 case GL_FRAMEBUFFER_BINDING:
4619 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4620 *num_written = 1;
4621 if (params) {
4622 Framebuffer* framebuffer =
4623 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4624 if (framebuffer) {
4625 GLuint client_id = 0;
4626 framebuffer_manager()->GetClientId(
4627 framebuffer->service_id(), &client_id);
4628 *params = client_id;
4629 } else {
4630 *params = 0;
4633 return true;
4634 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4635 *num_written = 1;
4636 if (params) {
4637 Framebuffer* framebuffer =
4638 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4639 if (framebuffer) {
4640 GLuint client_id = 0;
4641 framebuffer_manager()->GetClientId(
4642 framebuffer->service_id(), &client_id);
4643 *params = client_id;
4644 } else {
4645 *params = 0;
4648 return true;
4649 case GL_RENDERBUFFER_BINDING:
4650 *num_written = 1;
4651 if (params) {
4652 Renderbuffer* renderbuffer =
4653 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4654 if (renderbuffer) {
4655 *params = renderbuffer->client_id();
4656 } else {
4657 *params = 0;
4660 return true;
4661 case GL_CURRENT_PROGRAM:
4662 *num_written = 1;
4663 if (params) {
4664 if (state_.current_program.get()) {
4665 GLuint client_id = 0;
4666 program_manager()->GetClientId(
4667 state_.current_program->service_id(), &client_id);
4668 *params = client_id;
4669 } else {
4670 *params = 0;
4673 return true;
4674 case GL_VERTEX_ARRAY_BINDING_OES:
4675 *num_written = 1;
4676 if (params) {
4677 if (state_.vertex_attrib_manager.get() !=
4678 state_.default_vertex_attrib_manager.get()) {
4679 GLuint client_id = 0;
4680 vertex_array_manager_->GetClientId(
4681 state_.vertex_attrib_manager->service_id(), &client_id);
4682 *params = client_id;
4683 } else {
4684 *params = 0;
4687 return true;
4688 case GL_TEXTURE_BINDING_2D:
4689 *num_written = 1;
4690 if (params) {
4691 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4692 if (unit.bound_texture_2d.get()) {
4693 *params = unit.bound_texture_2d->client_id();
4694 } else {
4695 *params = 0;
4698 return true;
4699 case GL_TEXTURE_BINDING_CUBE_MAP:
4700 *num_written = 1;
4701 if (params) {
4702 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4703 if (unit.bound_texture_cube_map.get()) {
4704 *params = unit.bound_texture_cube_map->client_id();
4705 } else {
4706 *params = 0;
4709 return true;
4710 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4711 *num_written = 1;
4712 if (params) {
4713 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4714 if (unit.bound_texture_external_oes.get()) {
4715 *params = unit.bound_texture_external_oes->client_id();
4716 } else {
4717 *params = 0;
4720 return true;
4721 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4722 *num_written = 1;
4723 if (params) {
4724 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4725 if (unit.bound_texture_rectangle_arb.get()) {
4726 *params = unit.bound_texture_rectangle_arb->client_id();
4727 } else {
4728 *params = 0;
4731 return true;
4732 case GL_UNPACK_FLIP_Y_CHROMIUM:
4733 *num_written = 1;
4734 if (params) {
4735 params[0] = unpack_flip_y_;
4737 return true;
4738 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4739 *num_written = 1;
4740 if (params) {
4741 params[0] = unpack_premultiply_alpha_;
4743 return true;
4744 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4745 *num_written = 1;
4746 if (params) {
4747 params[0] = unpack_unpremultiply_alpha_;
4749 return true;
4750 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4751 *num_written = 1;
4752 if (params) {
4753 params[0] = group_->bind_generates_resource() ? 1 : 0;
4755 return true;
4756 default:
4757 if (pname >= GL_DRAW_BUFFER0_ARB &&
4758 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4759 *num_written = 1;
4760 if (params) {
4761 Framebuffer* framebuffer =
4762 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4763 if (framebuffer) {
4764 params[0] = framebuffer->GetDrawBuffer(pname);
4765 } else { // backbuffer
4766 if (pname == GL_DRAW_BUFFER0_ARB)
4767 params[0] = group_->draw_buffer();
4768 else
4769 params[0] = GL_NONE;
4772 return true;
4774 *num_written = util_.GLGetNumValuesReturned(pname);
4775 return false;
4779 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4780 GLenum pname, GLsizei* num_values) {
4781 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4782 return true;
4784 return GetHelper(pname, NULL, num_values);
4787 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4788 if (GL_MAX_SAMPLES == pname &&
4789 features().use_img_for_multisampled_render_to_texture) {
4790 return GL_MAX_SAMPLES_IMG;
4792 return pname;
4795 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4796 DCHECK(params);
4797 GLsizei num_written = 0;
4798 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4799 scoped_ptr<GLint[]> values(new GLint[num_written]);
4800 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4801 GetHelper(pname, values.get(), &num_written);
4803 for (GLsizei ii = 0; ii < num_written; ++ii) {
4804 params[ii] = static_cast<GLboolean>(values[ii]);
4806 } else {
4807 pname = AdjustGetPname(pname);
4808 glGetBooleanv(pname, params);
4812 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4813 DCHECK(params);
4814 GLsizei num_written = 0;
4815 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4816 if (GetHelper(pname, NULL, &num_written)) {
4817 scoped_ptr<GLint[]> values(new GLint[num_written]);
4818 GetHelper(pname, values.get(), &num_written);
4819 for (GLsizei ii = 0; ii < num_written; ++ii) {
4820 params[ii] = static_cast<GLfloat>(values[ii]);
4822 } else {
4823 pname = AdjustGetPname(pname);
4824 glGetFloatv(pname, params);
4829 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4830 DCHECK(params);
4831 GLsizei num_written;
4832 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4833 !GetHelper(pname, params, &num_written)) {
4834 pname = AdjustGetPname(pname);
4835 glGetIntegerv(pname, params);
4839 void GLES2DecoderImpl::DoGetProgramiv(
4840 GLuint program_id, GLenum pname, GLint* params) {
4841 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4842 if (!program) {
4843 return;
4845 program->GetProgramiv(pname, params);
4848 void GLES2DecoderImpl::DoGetBufferParameteriv(
4849 GLenum target, GLenum pname, GLint* params) {
4850 // Just delegate it. Some validation is actually done before this.
4851 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4852 &state_, target, pname, params);
4855 void GLES2DecoderImpl::DoBindAttribLocation(
4856 GLuint program_id, GLuint index, const char* name) {
4857 if (!StringIsValidForGLES(name)) {
4858 LOCAL_SET_GL_ERROR(
4859 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4860 return;
4862 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4863 LOCAL_SET_GL_ERROR(
4864 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4865 return;
4867 if (index >= group_->max_vertex_attribs()) {
4868 LOCAL_SET_GL_ERROR(
4869 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4870 return;
4872 Program* program = GetProgramInfoNotShader(
4873 program_id, "glBindAttribLocation");
4874 if (!program) {
4875 return;
4877 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4878 glBindAttribLocation(program->service_id(), index, name);
4881 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4882 uint32 immediate_data_size,
4883 const void* cmd_data) {
4884 const gles2::cmds::BindAttribLocationBucket& c =
4885 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
4886 GLuint program = static_cast<GLuint>(c.program);
4887 GLuint index = static_cast<GLuint>(c.index);
4888 Bucket* bucket = GetBucket(c.name_bucket_id);
4889 if (!bucket || bucket->size() == 0) {
4890 return error::kInvalidArguments;
4892 std::string name_str;
4893 if (!bucket->GetAsString(&name_str)) {
4894 return error::kInvalidArguments;
4896 DoBindAttribLocation(program, index, name_str.c_str());
4897 return error::kNoError;
4900 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4901 GLuint program_id, GLint location, const char* name) {
4902 if (!StringIsValidForGLES(name)) {
4903 LOCAL_SET_GL_ERROR(
4904 GL_INVALID_VALUE,
4905 "glBindUniformLocationCHROMIUM", "Invalid character");
4906 return;
4908 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4909 LOCAL_SET_GL_ERROR(
4910 GL_INVALID_OPERATION,
4911 "glBindUniformLocationCHROMIUM", "reserved prefix");
4912 return;
4914 if (location < 0 || static_cast<uint32>(location) >=
4915 (group_->max_fragment_uniform_vectors() +
4916 group_->max_vertex_uniform_vectors()) * 4) {
4917 LOCAL_SET_GL_ERROR(
4918 GL_INVALID_VALUE,
4919 "glBindUniformLocationCHROMIUM", "location out of range");
4920 return;
4922 Program* program = GetProgramInfoNotShader(
4923 program_id, "glBindUniformLocationCHROMIUM");
4924 if (!program) {
4925 return;
4927 if (!program->SetUniformLocationBinding(name, location)) {
4928 LOCAL_SET_GL_ERROR(
4929 GL_INVALID_VALUE,
4930 "glBindUniformLocationCHROMIUM", "location out of range");
4934 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4935 uint32 immediate_data_size,
4936 const void* cmd_data) {
4937 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
4938 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
4939 cmd_data);
4940 GLuint program = static_cast<GLuint>(c.program);
4941 GLint location = static_cast<GLint>(c.location);
4942 Bucket* bucket = GetBucket(c.name_bucket_id);
4943 if (!bucket || bucket->size() == 0) {
4944 return error::kInvalidArguments;
4946 std::string name_str;
4947 if (!bucket->GetAsString(&name_str)) {
4948 return error::kInvalidArguments;
4950 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4951 return error::kNoError;
4954 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
4955 const void* cmd_data) {
4956 const gles2::cmds::DeleteShader& c =
4957 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
4958 GLuint client_id = c.shader;
4959 if (client_id) {
4960 Shader* shader = GetShader(client_id);
4961 if (shader) {
4962 if (!shader->IsDeleted()) {
4963 glDeleteShader(shader->service_id());
4964 shader_manager()->MarkAsDeleted(shader);
4966 } else {
4967 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4970 return error::kNoError;
4973 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
4974 const void* cmd_data) {
4975 const gles2::cmds::DeleteProgram& c =
4976 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
4977 GLuint client_id = c.program;
4978 if (client_id) {
4979 Program* program = GetProgram(client_id);
4980 if (program) {
4981 if (!program->IsDeleted()) {
4982 program_manager()->MarkAsDeleted(shader_manager(), program);
4984 } else {
4985 LOCAL_SET_GL_ERROR(
4986 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4989 return error::kNoError;
4992 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4993 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4994 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4995 for (GLsizei ii = 0; ii < n; ++ii) {
4996 id_allocator->FreeID(ids[ii]);
5000 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
5001 uint32 immediate_data_size,
5002 const void* cmd_data) {
5003 const gles2::cmds::DeleteSharedIdsCHROMIUM& c =
5004 *static_cast<const gles2::cmds::DeleteSharedIdsCHROMIUM*>(cmd_data);
5005 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
5006 GLsizei n = static_cast<GLsizei>(c.n);
5007 uint32 data_size;
5008 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5009 return error::kOutOfBounds;
5011 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
5012 c.ids_shm_id, c.ids_shm_offset, data_size);
5013 if (n < 0) {
5014 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
5015 return error::kNoError;
5017 if (ids == NULL) {
5018 return error::kOutOfBounds;
5020 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
5021 return error::kNoError;
5024 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
5025 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
5026 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
5027 if (id_offset == 0) {
5028 for (GLsizei ii = 0; ii < n; ++ii) {
5029 ids[ii] = id_allocator->AllocateID();
5031 } else {
5032 for (GLsizei ii = 0; ii < n; ++ii) {
5033 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
5034 id_offset = ids[ii] + 1;
5039 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
5040 uint32 immediate_data_size,
5041 const void* cmd_data) {
5042 const gles2::cmds::GenSharedIdsCHROMIUM& c =
5043 *static_cast<const gles2::cmds::GenSharedIdsCHROMIUM*>(cmd_data);
5044 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
5045 GLuint id_offset = static_cast<GLuint>(c.id_offset);
5046 GLsizei n = static_cast<GLsizei>(c.n);
5047 uint32 data_size;
5048 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5049 return error::kOutOfBounds;
5051 GLuint* ids = GetSharedMemoryAs<GLuint*>(
5052 c.ids_shm_id, c.ids_shm_offset, data_size);
5053 if (n < 0) {
5054 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
5055 return error::kNoError;
5057 if (ids == NULL) {
5058 return error::kOutOfBounds;
5060 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
5061 return error::kNoError;
5064 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
5065 GLuint namespace_id, GLsizei n, const GLuint* ids) {
5066 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
5067 for (GLsizei ii = 0; ii < n; ++ii) {
5068 if (!id_allocator->MarkAsUsed(ids[ii])) {
5069 for (GLsizei jj = 0; jj < ii; ++jj) {
5070 id_allocator->FreeID(ids[jj]);
5072 LOCAL_SET_GL_ERROR(
5073 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
5074 "attempt to register id that already exists");
5075 return;
5080 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
5081 uint32 immediate_data_size,
5082 const void* cmd_data) {
5083 const gles2::cmds::RegisterSharedIdsCHROMIUM& c =
5084 *static_cast<const gles2::cmds::RegisterSharedIdsCHROMIUM*>(cmd_data);
5085 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
5086 GLsizei n = static_cast<GLsizei>(c.n);
5087 uint32 data_size;
5088 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5089 return error::kOutOfBounds;
5091 GLuint* ids = GetSharedMemoryAs<GLuint*>(
5092 c.ids_shm_id, c.ids_shm_offset, data_size);
5093 if (n < 0) {
5094 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
5095 return error::kNoError;
5097 if (ids == NULL) {
5098 return error::kOutOfBounds;
5100 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
5101 return error::kNoError;
5104 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5105 DCHECK(!ShouldDeferDraws());
5106 if (CheckBoundFramebuffersValid("glClear")) {
5107 ApplyDirtyState();
5108 glClear(mask);
5110 return error::kNoError;
5113 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5114 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5115 GLuint client_renderbuffer_id) {
5116 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5117 if (!framebuffer) {
5118 LOCAL_SET_GL_ERROR(
5119 GL_INVALID_OPERATION,
5120 "glFramebufferRenderbuffer", "no framebuffer bound");
5121 return;
5123 GLuint service_id = 0;
5124 Renderbuffer* renderbuffer = NULL;
5125 if (client_renderbuffer_id) {
5126 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5127 if (!renderbuffer) {
5128 LOCAL_SET_GL_ERROR(
5129 GL_INVALID_OPERATION,
5130 "glFramebufferRenderbuffer", "unknown renderbuffer");
5131 return;
5133 service_id = renderbuffer->service_id();
5135 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5136 glFramebufferRenderbufferEXT(
5137 target, attachment, renderbuffertarget, service_id);
5138 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5139 if (error == GL_NO_ERROR) {
5140 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5142 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5143 framebuffer_state_.clear_state_dirty = true;
5145 OnFboChanged();
5148 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5149 if (SetCapabilityState(cap, false)) {
5150 glDisable(cap);
5154 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5155 if (SetCapabilityState(cap, true)) {
5156 glEnable(cap);
5160 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5161 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5162 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5163 glDepthRange(znear, zfar);
5166 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5167 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5168 state_.sample_coverage_invert = (invert != 0);
5169 glSampleCoverage(state_.sample_coverage_value, invert);
5172 // Assumes framebuffer is complete.
5173 void GLES2DecoderImpl::ClearUnclearedAttachments(
5174 GLenum target, Framebuffer* framebuffer) {
5175 if (target == GL_READ_FRAMEBUFFER_EXT) {
5176 // bind this to the DRAW point, clear then bind back to READ
5177 // TODO(gman): I don't think there is any guarantee that an FBO that
5178 // is complete on the READ attachment will be complete as a DRAW
5179 // attachment.
5180 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5181 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5183 GLbitfield clear_bits = 0;
5184 if (framebuffer->HasUnclearedColorAttachments()) {
5185 glClearColor(
5186 0.0f, 0.0f, 0.0f,
5187 (GLES2Util::GetChannelsForFormat(
5188 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5189 1.0f);
5190 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5191 clear_bits |= GL_COLOR_BUFFER_BIT;
5192 if (feature_info_->feature_flags().ext_draw_buffers)
5193 framebuffer->PrepareDrawBuffersForClear();
5196 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5197 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5198 glClearStencil(0);
5199 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5200 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5201 clear_bits |= GL_STENCIL_BUFFER_BIT;
5204 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5205 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5206 glClearDepth(1.0f);
5207 state_.SetDeviceDepthMask(GL_TRUE);
5208 clear_bits |= GL_DEPTH_BUFFER_BIT;
5211 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5212 glClear(clear_bits);
5214 if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0 &&
5215 feature_info_->feature_flags().ext_draw_buffers)
5216 framebuffer->RestoreDrawBuffersAfterClear();
5218 framebuffer_manager()->MarkAttachmentsAsCleared(
5219 framebuffer, renderbuffer_manager(), texture_manager());
5221 RestoreClearState();
5223 if (target == GL_READ_FRAMEBUFFER_EXT) {
5224 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5225 Framebuffer* draw_framebuffer =
5226 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5227 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5228 GetBackbufferServiceId();
5229 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5233 void GLES2DecoderImpl::RestoreClearState() {
5234 framebuffer_state_.clear_state_dirty = true;
5235 glClearColor(
5236 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5237 state_.color_clear_alpha);
5238 glClearStencil(state_.stencil_clear);
5239 glClearDepth(state_.depth_clear);
5240 if (state_.enable_flags.scissor_test) {
5241 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5245 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5246 Framebuffer* framebuffer =
5247 GetFramebufferInfoForTarget(target);
5248 if (!framebuffer) {
5249 return GL_FRAMEBUFFER_COMPLETE;
5251 GLenum completeness = framebuffer->IsPossiblyComplete();
5252 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5253 return completeness;
5255 return framebuffer->GetStatus(texture_manager(), target);
5258 void GLES2DecoderImpl::DoFramebufferTexture2D(
5259 GLenum target, GLenum attachment, GLenum textarget,
5260 GLuint client_texture_id, GLint level) {
5261 DoFramebufferTexture2DCommon(
5262 "glFramebufferTexture2D", target, attachment,
5263 textarget, client_texture_id, level, 0);
5266 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5267 GLenum target, GLenum attachment, GLenum textarget,
5268 GLuint client_texture_id, GLint level, GLsizei samples) {
5269 DoFramebufferTexture2DCommon(
5270 "glFramebufferTexture2DMultisample", target, attachment,
5271 textarget, client_texture_id, level, samples);
5274 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5275 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5276 GLuint client_texture_id, GLint level, GLsizei samples) {
5277 if (samples > renderbuffer_manager()->max_samples()) {
5278 LOCAL_SET_GL_ERROR(
5279 GL_INVALID_VALUE,
5280 "glFramebufferTexture2DMultisample", "samples too large");
5281 return;
5283 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5284 if (!framebuffer) {
5285 LOCAL_SET_GL_ERROR(
5286 GL_INVALID_OPERATION,
5287 name, "no framebuffer bound.");
5288 return;
5290 GLuint service_id = 0;
5291 TextureRef* texture_ref = NULL;
5292 if (client_texture_id) {
5293 texture_ref = GetTexture(client_texture_id);
5294 if (!texture_ref) {
5295 LOCAL_SET_GL_ERROR(
5296 GL_INVALID_OPERATION,
5297 name, "unknown texture_ref");
5298 return;
5300 service_id = texture_ref->service_id();
5303 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5304 LOCAL_SET_GL_ERROR(
5305 GL_INVALID_VALUE,
5306 name, "level out of range");
5307 return;
5310 if (texture_ref)
5311 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5313 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5314 if (0 == samples) {
5315 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5316 } else {
5317 if (features().use_img_for_multisampled_render_to_texture) {
5318 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5319 service_id, level, samples);
5320 } else {
5321 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5322 service_id, level, samples);
5325 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5326 if (error == GL_NO_ERROR) {
5327 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5328 samples);
5330 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5331 framebuffer_state_.clear_state_dirty = true;
5334 if (texture_ref)
5335 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5337 OnFboChanged();
5340 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5341 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5342 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5343 if (!framebuffer) {
5344 LOCAL_SET_GL_ERROR(
5345 GL_INVALID_OPERATION,
5346 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5347 return;
5349 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5350 const Framebuffer::Attachment* attachment_object =
5351 framebuffer->GetAttachment(attachment);
5352 *params = attachment_object ? attachment_object->object_name() : 0;
5353 } else {
5354 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5355 features().use_img_for_multisampled_render_to_texture) {
5356 pname = GL_TEXTURE_SAMPLES_IMG;
5358 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5362 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5363 GLenum target, GLenum pname, GLint* params) {
5364 Renderbuffer* renderbuffer =
5365 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5366 if (!renderbuffer) {
5367 LOCAL_SET_GL_ERROR(
5368 GL_INVALID_OPERATION,
5369 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5370 return;
5373 EnsureRenderbufferBound();
5374 switch (pname) {
5375 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5376 *params = renderbuffer->internal_format();
5377 break;
5378 case GL_RENDERBUFFER_WIDTH:
5379 *params = renderbuffer->width();
5380 break;
5381 case GL_RENDERBUFFER_HEIGHT:
5382 *params = renderbuffer->height();
5383 break;
5384 case GL_RENDERBUFFER_SAMPLES_EXT:
5385 if (features().use_img_for_multisampled_render_to_texture) {
5386 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5387 params);
5388 } else {
5389 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5390 params);
5392 default:
5393 glGetRenderbufferParameterivEXT(target, pname, params);
5394 break;
5398 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5399 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5400 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5401 GLbitfield mask, GLenum filter) {
5402 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5404 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5405 return;
5408 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5409 BlitFramebufferHelper(
5410 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5411 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5412 state_.enable_flags.scissor_test);
5415 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5416 if (!state_.bound_renderbuffer_valid) {
5417 state_.bound_renderbuffer_valid = true;
5418 glBindRenderbufferEXT(GL_RENDERBUFFER,
5419 state_.bound_renderbuffer.get()
5420 ? state_.bound_renderbuffer->service_id()
5421 : 0);
5425 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5426 const FeatureInfo* feature_info,
5427 GLenum target,
5428 GLsizei samples,
5429 GLenum internal_format,
5430 GLsizei width,
5431 GLsizei height) {
5432 // TODO(sievers): This could be resolved at the GL binding level, but the
5433 // binding process is currently a bit too 'brute force'.
5434 if (feature_info->feature_flags().is_angle) {
5435 glRenderbufferStorageMultisampleANGLE(
5436 target, samples, internal_format, width, height);
5437 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5438 glRenderbufferStorageMultisample(
5439 target, samples, internal_format, width, height);
5440 } else {
5441 glRenderbufferStorageMultisampleEXT(
5442 target, samples, internal_format, width, height);
5446 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5447 GLint srcY0,
5448 GLint srcX1,
5449 GLint srcY1,
5450 GLint dstX0,
5451 GLint dstY0,
5452 GLint dstX1,
5453 GLint dstY1,
5454 GLbitfield mask,
5455 GLenum filter) {
5456 // TODO(sievers): This could be resolved at the GL binding level, but the
5457 // binding process is currently a bit too 'brute force'.
5458 if (feature_info_->feature_flags().is_angle) {
5459 glBlitFramebufferANGLE(
5460 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5461 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5462 glBlitFramebuffer(
5463 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5464 } else {
5465 glBlitFramebufferEXT(
5466 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5470 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5471 GLsizei samples,
5472 GLenum internalformat,
5473 GLsizei width,
5474 GLsizei height) {
5475 if (samples > renderbuffer_manager()->max_samples()) {
5476 LOCAL_SET_GL_ERROR(
5477 GL_INVALID_VALUE,
5478 "glRenderbufferStorageMultisample", "samples too large");
5479 return false;
5482 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5483 height > renderbuffer_manager()->max_renderbuffer_size()) {
5484 LOCAL_SET_GL_ERROR(
5485 GL_INVALID_VALUE,
5486 "glRenderbufferStorageMultisample", "dimensions too large");
5487 return false;
5490 uint32 estimated_size = 0;
5491 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5492 width, height, samples, internalformat, &estimated_size)) {
5493 LOCAL_SET_GL_ERROR(
5494 GL_OUT_OF_MEMORY,
5495 "glRenderbufferStorageMultisample", "dimensions too large");
5496 return false;
5499 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5500 LOCAL_SET_GL_ERROR(
5501 GL_OUT_OF_MEMORY,
5502 "glRenderbufferStorageMultisample", "out of memory");
5503 return false;
5506 return true;
5509 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5510 GLenum target, GLsizei samples, GLenum internalformat,
5511 GLsizei width, GLsizei height) {
5512 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5513 if (!renderbuffer) {
5514 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5515 "glRenderbufferStorageMultisampleCHROMIUM",
5516 "no renderbuffer bound");
5517 return;
5520 if (!ValidateRenderbufferStorageMultisample(
5521 samples, internalformat, width, height)) {
5522 return;
5525 EnsureRenderbufferBound();
5526 GLenum impl_format =
5527 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5528 internalformat);
5529 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5530 "glRenderbufferStorageMultisampleCHROMIUM");
5531 RenderbufferStorageMultisampleHelper(
5532 feature_info_.get(), target, samples, impl_format, width, height);
5533 GLenum error =
5534 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5535 if (error == GL_NO_ERROR) {
5537 if (workarounds().validate_multisample_buffer_allocation) {
5538 if (!VerifyMultisampleRenderbufferIntegrity(
5539 renderbuffer->service_id(), impl_format)) {
5540 LOCAL_SET_GL_ERROR(
5541 GL_OUT_OF_MEMORY,
5542 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5543 return;
5547 // TODO(gman): If renderbuffers tracked which framebuffers they were
5548 // attached to we could just mark those framebuffers as not complete.
5549 framebuffer_manager()->IncFramebufferStateChangeCount();
5550 renderbuffer_manager()->SetInfo(
5551 renderbuffer, samples, internalformat, width, height);
5555 // This is the handler for multisampled_render_to_texture extensions.
5556 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5557 GLenum target, GLsizei samples, GLenum internalformat,
5558 GLsizei width, GLsizei height) {
5559 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5560 if (!renderbuffer) {
5561 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5562 "glRenderbufferStorageMultisampleEXT",
5563 "no renderbuffer bound");
5564 return;
5567 if (!ValidateRenderbufferStorageMultisample(
5568 samples, internalformat, width, height)) {
5569 return;
5572 EnsureRenderbufferBound();
5573 GLenum impl_format =
5574 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5575 internalformat);
5576 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5577 if (features().use_img_for_multisampled_render_to_texture) {
5578 glRenderbufferStorageMultisampleIMG(
5579 target, samples, impl_format, width, height);
5580 } else {
5581 glRenderbufferStorageMultisampleEXT(
5582 target, samples, impl_format, width, height);
5584 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5585 if (error == GL_NO_ERROR) {
5586 // TODO(gman): If renderbuffers tracked which framebuffers they were
5587 // attached to we could just mark those framebuffers as not complete.
5588 framebuffer_manager()->IncFramebufferStateChangeCount();
5589 renderbuffer_manager()->SetInfo(
5590 renderbuffer, samples, internalformat, width, height);
5594 // This function validates the allocation of a multisampled renderbuffer
5595 // by clearing it to a key color, blitting the contents to a texture, and
5596 // reading back the color to ensure it matches the key.
5597 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5598 GLuint renderbuffer, GLenum format) {
5600 // Only validate color buffers.
5601 // These formats have been selected because they are very common or are known
5602 // to be used by the WebGL backbuffer. If problems are observed with other
5603 // color formats they can be added here.
5604 switch(format) {
5605 case GL_RGB:
5606 case GL_RGB8:
5607 case GL_RGBA:
5608 case GL_RGBA8:
5609 break;
5610 default:
5611 return true;
5614 GLint draw_framebuffer, read_framebuffer;
5616 // Cache framebuffer and texture bindings.
5617 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5618 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5620 if (!validation_texture_) {
5621 GLint bound_texture;
5622 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5624 // Create additional resources needed for the verification.
5625 glGenTextures(1, &validation_texture_);
5626 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5627 glGenFramebuffersEXT(1, &validation_fbo_);
5629 // Texture only needs to be 1x1.
5630 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5631 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5632 GL_UNSIGNED_BYTE, NULL);
5634 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5635 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5636 GL_TEXTURE_2D, validation_texture_, 0);
5638 glBindTexture(GL_TEXTURE_2D, bound_texture);
5641 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5642 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5643 GL_RENDERBUFFER, renderbuffer);
5645 // Cache current state and reset it to the values we require.
5646 GLboolean scissor_enabled = false;
5647 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5648 if (scissor_enabled)
5649 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5651 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5652 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5653 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5655 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5656 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5657 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5659 // Clear the buffer to the desired key color.
5660 glClear(GL_COLOR_BUFFER_BIT);
5662 // Blit from the multisample buffer to a standard texture.
5663 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5664 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5666 BlitFramebufferHelper(
5667 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5669 // Read a pixel from the buffer.
5670 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5672 unsigned char pixel[3] = {0, 0, 0};
5673 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5675 // Detach the renderbuffer.
5676 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5677 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5678 GL_RENDERBUFFER, 0);
5680 // Restore cached state.
5681 if (scissor_enabled)
5682 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5684 state_.SetDeviceColorMask(
5685 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5686 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5687 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5688 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5690 // Return true if the pixel matched the desired key color.
5691 return (pixel[0] == 0xFF &&
5692 pixel[1] == 0x00 &&
5693 pixel[2] == 0xFF);
5696 void GLES2DecoderImpl::DoRenderbufferStorage(
5697 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5698 Renderbuffer* renderbuffer =
5699 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5700 if (!renderbuffer) {
5701 LOCAL_SET_GL_ERROR(
5702 GL_INVALID_OPERATION,
5703 "glRenderbufferStorage", "no renderbuffer bound");
5704 return;
5707 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5708 height > renderbuffer_manager()->max_renderbuffer_size()) {
5709 LOCAL_SET_GL_ERROR(
5710 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5711 return;
5714 uint32 estimated_size = 0;
5715 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5716 width, height, 1, internalformat, &estimated_size)) {
5717 LOCAL_SET_GL_ERROR(
5718 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5719 return;
5722 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5723 LOCAL_SET_GL_ERROR(
5724 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5725 return;
5728 EnsureRenderbufferBound();
5729 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5730 glRenderbufferStorageEXT(
5731 target,
5732 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5733 internalformat),
5734 width,
5735 height);
5736 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5737 if (error == GL_NO_ERROR) {
5738 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5739 // we could just mark those framebuffers as not complete.
5740 framebuffer_manager()->IncFramebufferStateChangeCount();
5741 renderbuffer_manager()->SetInfo(
5742 renderbuffer, 1, internalformat, width, height);
5746 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5747 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5748 Program* program = GetProgramInfoNotShader(
5749 program_id, "glLinkProgram");
5750 if (!program) {
5751 return;
5754 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5755 ShaderTranslator* vertex_translator = NULL;
5756 ShaderTranslator* fragment_translator = NULL;
5757 if (use_shader_translator_) {
5758 vertex_translator = vertex_translator_.get();
5759 fragment_translator = fragment_translator_.get();
5761 if (program->Link(shader_manager(),
5762 vertex_translator,
5763 fragment_translator,
5764 workarounds().count_all_in_varyings_packing ?
5765 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5766 shader_cache_callback_)) {
5767 if (program == state_.current_program.get()) {
5768 if (workarounds().use_current_program_after_successful_link)
5769 glUseProgram(program->service_id());
5770 if (workarounds().clear_uniforms_before_first_program_use)
5771 program_manager()->ClearUniforms(program);
5775 // LinkProgram can be very slow. Exit command processing to allow for
5776 // context preemption and GPU watchdog checks.
5777 ExitCommandProcessingEarly();
5780 void GLES2DecoderImpl::DoTexParameterf(
5781 GLenum target, GLenum pname, GLfloat param) {
5782 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5783 &state_, target);
5784 if (!texture) {
5785 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5786 return;
5789 texture_manager()->SetParameterf(
5790 "glTexParameterf", GetErrorState(), texture, pname, param);
5793 void GLES2DecoderImpl::DoTexParameteri(
5794 GLenum target, GLenum pname, GLint param) {
5795 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5796 &state_, target);
5797 if (!texture) {
5798 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5799 return;
5802 texture_manager()->SetParameteri(
5803 "glTexParameteri", GetErrorState(), texture, pname, param);
5806 void GLES2DecoderImpl::DoTexParameterfv(
5807 GLenum target, GLenum pname, const GLfloat* params) {
5808 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5809 &state_, target);
5810 if (!texture) {
5811 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5812 return;
5815 texture_manager()->SetParameterf(
5816 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5819 void GLES2DecoderImpl::DoTexParameteriv(
5820 GLenum target, GLenum pname, const GLint* params) {
5821 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5822 &state_, target);
5823 if (!texture) {
5824 LOCAL_SET_GL_ERROR(
5825 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5826 return;
5829 texture_manager()->SetParameteri(
5830 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5833 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5834 if (!state_.current_program.get()) {
5835 // The program does not exist.
5836 LOCAL_SET_GL_ERROR(
5837 GL_INVALID_OPERATION, function_name, "no program in use");
5838 return false;
5840 if (!state_.current_program->InUse()) {
5841 LOCAL_SET_GL_ERROR(
5842 GL_INVALID_OPERATION, function_name, "program not linked");
5843 return false;
5845 return true;
5848 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5849 GLint location, const char* function_name) {
5850 if (!CheckCurrentProgram(function_name)) {
5851 return false;
5853 return location != -1;
5856 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5857 GLint fake_location,
5858 const char* function_name,
5859 Program::UniformApiType api_type,
5860 GLint* real_location,
5861 GLenum* type,
5862 GLsizei* count) {
5863 DCHECK(type);
5864 DCHECK(count);
5865 DCHECK(real_location);
5867 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5868 return false;
5870 GLint array_index = -1;
5871 const Program::UniformInfo* info =
5872 state_.current_program->GetUniformInfoByFakeLocation(
5873 fake_location, real_location, &array_index);
5874 if (!info) {
5875 LOCAL_SET_GL_ERROR(
5876 GL_INVALID_OPERATION, function_name, "unknown location");
5877 return false;
5880 if ((api_type & info->accepts_api_type) == 0) {
5881 LOCAL_SET_GL_ERROR(
5882 GL_INVALID_OPERATION, function_name,
5883 "wrong uniform function for type");
5884 return false;
5886 if (*count > 1 && !info->is_array) {
5887 LOCAL_SET_GL_ERROR(
5888 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5889 return false;
5891 *count = std::min(info->size - array_index, *count);
5892 if (*count <= 0) {
5893 return false;
5895 *type = info->type;
5896 return true;
5899 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5900 GLenum type = 0;
5901 GLsizei count = 1;
5902 GLint real_location = -1;
5903 if (!PrepForSetUniformByLocation(fake_location,
5904 "glUniform1i",
5905 Program::kUniform1i,
5906 &real_location,
5907 &type,
5908 &count)) {
5909 return;
5911 if (!state_.current_program->SetSamplers(
5912 state_.texture_units.size(), fake_location, 1, &v0)) {
5913 LOCAL_SET_GL_ERROR(
5914 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5915 return;
5917 glUniform1i(real_location, v0);
5920 void GLES2DecoderImpl::DoUniform1iv(
5921 GLint fake_location, GLsizei count, const GLint *value) {
5922 GLenum type = 0;
5923 GLint real_location = -1;
5924 if (!PrepForSetUniformByLocation(fake_location,
5925 "glUniform1iv",
5926 Program::kUniform1i,
5927 &real_location,
5928 &type,
5929 &count)) {
5930 return;
5932 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5933 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5934 if (!state_.current_program->SetSamplers(
5935 state_.texture_units.size(), fake_location, count, value)) {
5936 LOCAL_SET_GL_ERROR(
5937 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5938 return;
5941 glUniform1iv(real_location, count, value);
5944 void GLES2DecoderImpl::DoUniform1fv(
5945 GLint fake_location, GLsizei count, const GLfloat* value) {
5946 GLenum type = 0;
5947 GLint real_location = -1;
5948 if (!PrepForSetUniformByLocation(fake_location,
5949 "glUniform1fv",
5950 Program::kUniform1f,
5951 &real_location,
5952 &type,
5953 &count)) {
5954 return;
5956 if (type == GL_BOOL) {
5957 scoped_ptr<GLint[]> temp(new GLint[count]);
5958 for (GLsizei ii = 0; ii < count; ++ii) {
5959 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5961 DoUniform1iv(real_location, count, temp.get());
5962 } else {
5963 glUniform1fv(real_location, count, value);
5967 void GLES2DecoderImpl::DoUniform2fv(
5968 GLint fake_location, GLsizei count, const GLfloat* value) {
5969 GLenum type = 0;
5970 GLint real_location = -1;
5971 if (!PrepForSetUniformByLocation(fake_location,
5972 "glUniform2fv",
5973 Program::kUniform2f,
5974 &real_location,
5975 &type,
5976 &count)) {
5977 return;
5979 if (type == GL_BOOL_VEC2) {
5980 GLsizei num_values = count * 2;
5981 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5982 for (GLsizei ii = 0; ii < num_values; ++ii) {
5983 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5985 glUniform2iv(real_location, count, temp.get());
5986 } else {
5987 glUniform2fv(real_location, count, value);
5991 void GLES2DecoderImpl::DoUniform3fv(
5992 GLint fake_location, GLsizei count, const GLfloat* value) {
5993 GLenum type = 0;
5994 GLint real_location = -1;
5995 if (!PrepForSetUniformByLocation(fake_location,
5996 "glUniform3fv",
5997 Program::kUniform3f,
5998 &real_location,
5999 &type,
6000 &count)) {
6001 return;
6003 if (type == GL_BOOL_VEC3) {
6004 GLsizei num_values = count * 3;
6005 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6006 for (GLsizei ii = 0; ii < num_values; ++ii) {
6007 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6009 glUniform3iv(real_location, count, temp.get());
6010 } else {
6011 glUniform3fv(real_location, count, value);
6015 void GLES2DecoderImpl::DoUniform4fv(
6016 GLint fake_location, GLsizei count, const GLfloat* value) {
6017 GLenum type = 0;
6018 GLint real_location = -1;
6019 if (!PrepForSetUniformByLocation(fake_location,
6020 "glUniform4fv",
6021 Program::kUniform4f,
6022 &real_location,
6023 &type,
6024 &count)) {
6025 return;
6027 if (type == GL_BOOL_VEC4) {
6028 GLsizei num_values = count * 4;
6029 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6030 for (GLsizei ii = 0; ii < num_values; ++ii) {
6031 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6033 glUniform4iv(real_location, count, temp.get());
6034 } else {
6035 glUniform4fv(real_location, count, value);
6039 void GLES2DecoderImpl::DoUniform2iv(
6040 GLint fake_location, GLsizei count, const GLint* value) {
6041 GLenum type = 0;
6042 GLint real_location = -1;
6043 if (!PrepForSetUniformByLocation(fake_location,
6044 "glUniform2iv",
6045 Program::kUniform2i,
6046 &real_location,
6047 &type,
6048 &count)) {
6049 return;
6051 glUniform2iv(real_location, count, value);
6054 void GLES2DecoderImpl::DoUniform3iv(
6055 GLint fake_location, GLsizei count, const GLint* value) {
6056 GLenum type = 0;
6057 GLint real_location = -1;
6058 if (!PrepForSetUniformByLocation(fake_location,
6059 "glUniform3iv",
6060 Program::kUniform3i,
6061 &real_location,
6062 &type,
6063 &count)) {
6064 return;
6066 glUniform3iv(real_location, count, value);
6069 void GLES2DecoderImpl::DoUniform4iv(
6070 GLint fake_location, GLsizei count, const GLint* value) {
6071 GLenum type = 0;
6072 GLint real_location = -1;
6073 if (!PrepForSetUniformByLocation(fake_location,
6074 "glUniform4iv",
6075 Program::kUniform4i,
6076 &real_location,
6077 &type,
6078 &count)) {
6079 return;
6081 glUniform4iv(real_location, count, value);
6084 void GLES2DecoderImpl::DoUniformMatrix2fv(
6085 GLint fake_location, GLsizei count, GLboolean transpose,
6086 const GLfloat* value) {
6087 GLenum type = 0;
6088 GLint real_location = -1;
6089 if (!PrepForSetUniformByLocation(fake_location,
6090 "glUniformMatrix2fv",
6091 Program::kUniformMatrix2f,
6092 &real_location,
6093 &type,
6094 &count)) {
6095 return;
6097 glUniformMatrix2fv(real_location, count, transpose, value);
6100 void GLES2DecoderImpl::DoUniformMatrix3fv(
6101 GLint fake_location, GLsizei count, GLboolean transpose,
6102 const GLfloat* value) {
6103 GLenum type = 0;
6104 GLint real_location = -1;
6105 if (!PrepForSetUniformByLocation(fake_location,
6106 "glUniformMatrix3fv",
6107 Program::kUniformMatrix3f,
6108 &real_location,
6109 &type,
6110 &count)) {
6111 return;
6113 glUniformMatrix3fv(real_location, count, transpose, value);
6116 void GLES2DecoderImpl::DoUniformMatrix4fv(
6117 GLint fake_location, GLsizei count, GLboolean transpose,
6118 const GLfloat* value) {
6119 GLenum type = 0;
6120 GLint real_location = -1;
6121 if (!PrepForSetUniformByLocation(fake_location,
6122 "glUniformMatrix4fv",
6123 Program::kUniformMatrix4f,
6124 &real_location,
6125 &type,
6126 &count)) {
6127 return;
6129 glUniformMatrix4fv(real_location, count, transpose, value);
6132 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6133 GLuint service_id = 0;
6134 Program* program = NULL;
6135 if (program_id) {
6136 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6137 if (!program) {
6138 return;
6140 if (!program->IsValid()) {
6141 // Program was not linked successfully. (ie, glLinkProgram)
6142 LOCAL_SET_GL_ERROR(
6143 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6144 return;
6146 service_id = program->service_id();
6148 if (state_.current_program.get()) {
6149 program_manager()->UnuseProgram(shader_manager(),
6150 state_.current_program.get());
6152 state_.current_program = program;
6153 LogClientServiceMapping("glUseProgram", program_id, service_id);
6154 glUseProgram(service_id);
6155 if (state_.current_program.get()) {
6156 program_manager()->UseProgram(state_.current_program.get());
6157 if (workarounds().clear_uniforms_before_first_program_use)
6158 program_manager()->ClearUniforms(program);
6162 void GLES2DecoderImpl::RenderWarning(
6163 const char* filename, int line, const std::string& msg) {
6164 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6167 void GLES2DecoderImpl::PerformanceWarning(
6168 const char* filename, int line, const std::string& msg) {
6169 logger_.LogMessage(filename, line,
6170 std::string("PERFORMANCE WARNING: ") + msg);
6173 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6174 Texture* texture, GLenum textarget) {
6175 // Image is already in use if texture is attached to a framebuffer.
6176 if (texture && !texture->IsAttachedToFramebuffer()) {
6177 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6178 if (image) {
6179 ScopedGLErrorSuppressor suppressor(
6180 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6181 GetErrorState());
6182 glBindTexture(textarget, texture->service_id());
6183 image->WillUseTexImage();
6184 RestoreCurrentTextureBindings(&state_, textarget);
6189 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6190 Texture* texture, GLenum textarget) {
6191 // Image is still in use if texture is attached to a framebuffer.
6192 if (texture && !texture->IsAttachedToFramebuffer()) {
6193 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6194 if (image) {
6195 ScopedGLErrorSuppressor suppressor(
6196 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6197 GetErrorState());
6198 glBindTexture(textarget, texture->service_id());
6199 image->DidUseTexImage();
6200 RestoreCurrentTextureBindings(&state_, textarget);
6205 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6206 DCHECK(state_.current_program.get());
6207 if (!texture_manager()->HaveUnrenderableTextures() &&
6208 !texture_manager()->HaveImages()) {
6209 return true;
6212 bool textures_set = false;
6213 const Program::SamplerIndices& sampler_indices =
6214 state_.current_program->sampler_indices();
6215 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6216 const Program::UniformInfo* uniform_info =
6217 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6218 DCHECK(uniform_info);
6219 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6220 GLuint texture_unit_index = uniform_info->texture_units[jj];
6221 if (texture_unit_index < state_.texture_units.size()) {
6222 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6223 TextureRef* texture_ref =
6224 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6225 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6226 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6227 textures_set = true;
6228 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6229 glBindTexture(
6230 textarget,
6231 texture_manager()->black_texture_id(uniform_info->type));
6232 LOCAL_RENDER_WARNING(
6233 std::string("texture bound to texture unit ") +
6234 base::IntToString(texture_unit_index) +
6235 " is not renderable. It maybe non-power-of-2 and have"
6236 " incompatible texture filtering or is not"
6237 " 'texture complete'");
6238 continue;
6241 if (textarget != GL_TEXTURE_CUBE_MAP) {
6242 Texture* texture = texture_ref->texture();
6243 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6244 if (image && !texture->IsAttachedToFramebuffer()) {
6245 ScopedGLErrorSuppressor suppressor(
6246 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6247 textures_set = true;
6248 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6249 image->WillUseTexImage();
6250 continue;
6254 // else: should this be an error?
6257 return !textures_set;
6260 void GLES2DecoderImpl::RestoreStateForTextures() {
6261 DCHECK(state_.current_program.get());
6262 const Program::SamplerIndices& sampler_indices =
6263 state_.current_program->sampler_indices();
6264 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6265 const Program::UniformInfo* uniform_info =
6266 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6267 DCHECK(uniform_info);
6268 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6269 GLuint texture_unit_index = uniform_info->texture_units[jj];
6270 if (texture_unit_index < state_.texture_units.size()) {
6271 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6272 TextureRef* texture_ref =
6273 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6274 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6275 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6276 // Get the texture_ref info that was previously bound here.
6277 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6278 ? texture_unit.bound_texture_2d.get()
6279 : texture_unit.bound_texture_cube_map.get();
6280 glBindTexture(texture_unit.bind_target,
6281 texture_ref ? texture_ref->service_id() : 0);
6282 continue;
6285 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6286 Texture* texture = texture_ref->texture();
6287 gfx::GLImage* image =
6288 texture->GetLevelImage(texture_unit.bind_target, 0);
6289 if (image && !texture->IsAttachedToFramebuffer()) {
6290 ScopedGLErrorSuppressor suppressor(
6291 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6292 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6293 image->DidUseTexImage();
6294 continue;
6300 // Set the active texture back to whatever the user had it as.
6301 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6304 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6305 // Only check if there are some uncleared textures.
6306 if (!texture_manager()->HaveUnsafeTextures()) {
6307 return true;
6310 // 1: Check all textures we are about to render with.
6311 if (state_.current_program.get()) {
6312 const Program::SamplerIndices& sampler_indices =
6313 state_.current_program->sampler_indices();
6314 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6315 const Program::UniformInfo* uniform_info =
6316 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6317 DCHECK(uniform_info);
6318 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6319 GLuint texture_unit_index = uniform_info->texture_units[jj];
6320 if (texture_unit_index < state_.texture_units.size()) {
6321 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6322 TextureRef* texture_ref =
6323 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6324 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6325 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6326 return false;
6333 return true;
6336 bool GLES2DecoderImpl::IsDrawValid(
6337 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6338 GLsizei primcount) {
6339 DCHECK(instanced || primcount == 1);
6341 // NOTE: We specifically do not check current_program->IsValid() because
6342 // it could never be invalid since glUseProgram would have failed. While
6343 // glLinkProgram could later mark the program as invalid the previous
6344 // valid program will still function if it is still the current program.
6345 if (!state_.current_program.get()) {
6346 // The program does not exist.
6347 // But GL says no ERROR.
6348 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6349 return false;
6352 return state_.vertex_attrib_manager
6353 ->ValidateBindings(function_name,
6354 this,
6355 feature_info_.get(),
6356 state_.current_program.get(),
6357 max_vertex_accessed,
6358 instanced,
6359 primcount);
6362 bool GLES2DecoderImpl::SimulateAttrib0(
6363 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6364 DCHECK(simulated);
6365 *simulated = false;
6367 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6368 return true;
6370 const VertexAttrib* attrib =
6371 state_.vertex_attrib_manager->GetVertexAttrib(0);
6372 // If it's enabled or it's not used then we don't need to do anything.
6373 bool attrib_0_used =
6374 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6375 if (attrib->enabled() && attrib_0_used) {
6376 return true;
6379 // Make a buffer with a single repeated vec4 value enough to
6380 // simulate the constant value that is supposed to be here.
6381 // This is required to emulate GLES2 on GL.
6382 GLuint num_vertices = max_vertex_accessed + 1;
6383 uint32 size_needed = 0;
6385 if (num_vertices == 0 ||
6386 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6387 size_needed > 0x7FFFFFFFU) {
6388 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6389 return false;
6392 LOCAL_PERFORMANCE_WARNING(
6393 "Attribute 0 is disabled. This has signficant performance penalty");
6395 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6396 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6398 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6399 if (new_buffer) {
6400 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6401 GLenum error = glGetError();
6402 if (error != GL_NO_ERROR) {
6403 LOCAL_SET_GL_ERROR(
6404 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6405 return false;
6409 const Vec4& value = state_.attrib_values[0];
6410 if (new_buffer ||
6411 (attrib_0_used &&
6412 (!attrib_0_buffer_matches_value_ ||
6413 (value.v[0] != attrib_0_value_.v[0] ||
6414 value.v[1] != attrib_0_value_.v[1] ||
6415 value.v[2] != attrib_0_value_.v[2] ||
6416 value.v[3] != attrib_0_value_.v[3])))) {
6417 std::vector<Vec4> temp(num_vertices, value);
6418 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6419 attrib_0_buffer_matches_value_ = true;
6420 attrib_0_value_ = value;
6421 attrib_0_size_ = size_needed;
6424 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6426 if (attrib->divisor())
6427 glVertexAttribDivisorANGLE(0, 0);
6429 *simulated = true;
6430 return true;
6433 void GLES2DecoderImpl::RestoreStateForAttrib(
6434 GLuint attrib_index, bool restore_array_binding) {
6435 const VertexAttrib* attrib =
6436 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6437 if (restore_array_binding) {
6438 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6439 Buffer* buffer = attrib->buffer();
6440 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6441 glVertexAttribPointer(
6442 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6443 attrib->gl_stride(), ptr);
6445 if (attrib->divisor())
6446 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6447 glBindBuffer(
6448 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6449 state_.bound_array_buffer->service_id() : 0);
6451 // Never touch vertex attribute 0's state (in particular, never
6452 // disable it) when running on desktop GL because it will never be
6453 // re-enabled.
6454 if (attrib_index != 0 ||
6455 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6456 if (attrib->enabled()) {
6457 glEnableVertexAttribArray(attrib_index);
6458 } else {
6459 glDisableVertexAttribArray(attrib_index);
6464 bool GLES2DecoderImpl::SimulateFixedAttribs(
6465 const char* function_name,
6466 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6467 DCHECK(simulated);
6468 *simulated = false;
6469 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6470 return true;
6472 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6473 return true;
6476 LOCAL_PERFORMANCE_WARNING(
6477 "GL_FIXED attributes have a signficant performance penalty");
6479 // NOTE: we could be smart and try to check if a buffer is used
6480 // twice in 2 different attribs, find the overlapping parts and therefore
6481 // duplicate the minimum amount of data but this whole code path is not meant
6482 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6483 // tests so we just add to the buffer attrib used.
6485 GLuint elements_needed = 0;
6486 const VertexAttribManager::VertexAttribList& enabled_attribs =
6487 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6488 for (VertexAttribManager::VertexAttribList::const_iterator it =
6489 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6490 const VertexAttrib* attrib = *it;
6491 const Program::VertexAttrib* attrib_info =
6492 state_.current_program->GetAttribInfoByLocation(attrib->index());
6493 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6494 max_vertex_accessed);
6495 GLuint num_vertices = max_accessed + 1;
6496 if (num_vertices == 0) {
6497 LOCAL_SET_GL_ERROR(
6498 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6499 return false;
6501 if (attrib_info &&
6502 attrib->CanAccess(max_accessed) &&
6503 attrib->type() == GL_FIXED) {
6504 uint32 elements_used = 0;
6505 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6506 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6507 LOCAL_SET_GL_ERROR(
6508 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6509 return false;
6514 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6515 uint32 size_needed = 0;
6516 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6517 size_needed > 0x7FFFFFFFU) {
6518 LOCAL_SET_GL_ERROR(
6519 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6520 return false;
6523 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6525 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6526 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6527 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6528 GLenum error = glGetError();
6529 if (error != GL_NO_ERROR) {
6530 LOCAL_SET_GL_ERROR(
6531 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6532 return false;
6536 // Copy the elements and convert to float
6537 GLintptr offset = 0;
6538 for (VertexAttribManager::VertexAttribList::const_iterator it =
6539 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6540 const VertexAttrib* attrib = *it;
6541 const Program::VertexAttrib* attrib_info =
6542 state_.current_program->GetAttribInfoByLocation(attrib->index());
6543 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6544 max_vertex_accessed);
6545 GLuint num_vertices = max_accessed + 1;
6546 if (num_vertices == 0) {
6547 LOCAL_SET_GL_ERROR(
6548 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6549 return false;
6551 if (attrib_info &&
6552 attrib->CanAccess(max_accessed) &&
6553 attrib->type() == GL_FIXED) {
6554 int num_elements = attrib->size() * kSizeOfFloat;
6555 int size = num_elements * num_vertices;
6556 scoped_ptr<float[]> data(new float[size]);
6557 const int32* src = reinterpret_cast<const int32 *>(
6558 attrib->buffer()->GetRange(attrib->offset(), size));
6559 const int32* end = src + num_elements;
6560 float* dst = data.get();
6561 while (src != end) {
6562 *dst++ = static_cast<float>(*src++) / 65536.0f;
6564 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6565 glVertexAttribPointer(
6566 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6567 reinterpret_cast<GLvoid*>(offset));
6568 offset += size;
6571 *simulated = true;
6572 return true;
6575 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6576 // There's no need to call glVertexAttribPointer because we shadow all the
6577 // settings and passing GL_FIXED to it will not work.
6578 glBindBuffer(
6579 GL_ARRAY_BUFFER,
6580 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6581 : 0);
6584 error::Error GLES2DecoderImpl::DoDrawArrays(
6585 const char* function_name,
6586 bool instanced,
6587 GLenum mode,
6588 GLint first,
6589 GLsizei count,
6590 GLsizei primcount) {
6591 error::Error error = WillAccessBoundFramebufferForDraw();
6592 if (error != error::kNoError)
6593 return error;
6594 if (!validators_->draw_mode.IsValid(mode)) {
6595 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6596 return error::kNoError;
6598 if (count < 0) {
6599 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6600 return error::kNoError;
6602 if (primcount < 0) {
6603 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6604 return error::kNoError;
6606 if (!CheckBoundFramebuffersValid(function_name)) {
6607 return error::kNoError;
6609 // We have to check this here because the prototype for glDrawArrays
6610 // is GLint not GLsizei.
6611 if (first < 0) {
6612 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6613 return error::kNoError;
6616 if (count == 0 || primcount == 0) {
6617 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6618 return error::kNoError;
6621 GLuint max_vertex_accessed = first + count - 1;
6622 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6623 if (!ClearUnclearedTextures()) {
6624 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6625 return error::kNoError;
6627 bool simulated_attrib_0 = false;
6628 if (!SimulateAttrib0(
6629 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6630 return error::kNoError;
6632 bool simulated_fixed_attribs = false;
6633 if (SimulateFixedAttribs(
6634 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6635 primcount)) {
6636 bool textures_set = !PrepareTexturesForRender();
6637 ApplyDirtyState();
6638 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6639 if (!instanced) {
6640 glDrawArrays(mode, first, count);
6641 } else {
6642 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6644 if (textures_set) {
6645 RestoreStateForTextures();
6647 if (simulated_fixed_attribs) {
6648 RestoreStateForSimulatedFixedAttribs();
6651 if (simulated_attrib_0) {
6652 // We don't have to restore attrib 0 generic data at the end of this
6653 // function even if it is simulated. This is because we will simulate
6654 // it in each draw call, and attrib 0 generic data queries use cached
6655 // values instead of passing down to the underlying driver.
6656 RestoreStateForAttrib(0, false);
6659 return error::kNoError;
6662 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
6663 const void* cmd_data) {
6664 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
6665 return DoDrawArrays("glDrawArrays",
6666 false,
6667 static_cast<GLenum>(c.mode),
6668 static_cast<GLint>(c.first),
6669 static_cast<GLsizei>(c.count),
6673 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6674 uint32 immediate_data_size,
6675 const void* cmd_data) {
6676 const gles2::cmds::DrawArraysInstancedANGLE& c =
6677 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
6678 if (!features().angle_instanced_arrays) {
6679 LOCAL_SET_GL_ERROR(
6680 GL_INVALID_OPERATION,
6681 "glDrawArraysInstancedANGLE", "function not available");
6682 return error::kNoError;
6684 return DoDrawArrays("glDrawArraysIntancedANGLE",
6685 true,
6686 static_cast<GLenum>(c.mode),
6687 static_cast<GLint>(c.first),
6688 static_cast<GLsizei>(c.count),
6689 static_cast<GLsizei>(c.primcount));
6692 error::Error GLES2DecoderImpl::DoDrawElements(
6693 const char* function_name,
6694 bool instanced,
6695 GLenum mode,
6696 GLsizei count,
6697 GLenum type,
6698 int32 offset,
6699 GLsizei primcount) {
6700 error::Error error = WillAccessBoundFramebufferForDraw();
6701 if (error != error::kNoError)
6702 return error;
6703 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6704 LOCAL_SET_GL_ERROR(
6705 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6706 return error::kNoError;
6709 if (count < 0) {
6710 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6711 return error::kNoError;
6713 if (offset < 0) {
6714 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6715 return error::kNoError;
6717 if (!validators_->draw_mode.IsValid(mode)) {
6718 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6719 return error::kNoError;
6721 if (!validators_->index_type.IsValid(type)) {
6722 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6723 return error::kNoError;
6725 if (primcount < 0) {
6726 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6727 return error::kNoError;
6730 if (!CheckBoundFramebuffersValid(function_name)) {
6731 return error::kNoError;
6734 if (count == 0 || primcount == 0) {
6735 return error::kNoError;
6738 GLuint max_vertex_accessed;
6739 Buffer* element_array_buffer =
6740 state_.vertex_attrib_manager->element_array_buffer();
6742 if (!element_array_buffer->GetMaxValueForRange(
6743 offset, count, type, &max_vertex_accessed)) {
6744 LOCAL_SET_GL_ERROR(
6745 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6746 return error::kNoError;
6749 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6750 if (!ClearUnclearedTextures()) {
6751 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6752 return error::kNoError;
6754 bool simulated_attrib_0 = false;
6755 if (!SimulateAttrib0(
6756 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6757 return error::kNoError;
6759 bool simulated_fixed_attribs = false;
6760 if (SimulateFixedAttribs(
6761 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6762 primcount)) {
6763 bool textures_set = !PrepareTexturesForRender();
6764 ApplyDirtyState();
6765 // TODO(gman): Refactor to hide these details in BufferManager or
6766 // VertexAttribManager.
6767 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6768 bool used_client_side_array = false;
6769 if (element_array_buffer->IsClientSideArray()) {
6770 used_client_side_array = true;
6771 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6772 indices = element_array_buffer->GetRange(offset, 0);
6775 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6776 if (!instanced) {
6777 glDrawElements(mode, count, type, indices);
6778 } else {
6779 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6782 if (used_client_side_array) {
6783 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6784 element_array_buffer->service_id());
6787 if (textures_set) {
6788 RestoreStateForTextures();
6790 if (simulated_fixed_attribs) {
6791 RestoreStateForSimulatedFixedAttribs();
6794 if (simulated_attrib_0) {
6795 // We don't have to restore attrib 0 generic data at the end of this
6796 // function even if it is simulated. This is because we will simulate
6797 // it in each draw call, and attrib 0 generic data queries use cached
6798 // values instead of passing down to the underlying driver.
6799 RestoreStateForAttrib(0, false);
6802 return error::kNoError;
6805 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
6806 const void* cmd_data) {
6807 const gles2::cmds::DrawElements& c =
6808 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
6809 return DoDrawElements("glDrawElements",
6810 false,
6811 static_cast<GLenum>(c.mode),
6812 static_cast<GLsizei>(c.count),
6813 static_cast<GLenum>(c.type),
6814 static_cast<int32>(c.index_offset),
6818 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6819 uint32 immediate_data_size,
6820 const void* cmd_data) {
6821 const gles2::cmds::DrawElementsInstancedANGLE& c =
6822 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
6823 if (!features().angle_instanced_arrays) {
6824 LOCAL_SET_GL_ERROR(
6825 GL_INVALID_OPERATION,
6826 "glDrawElementsInstancedANGLE", "function not available");
6827 return error::kNoError;
6829 return DoDrawElements("glDrawElementsInstancedANGLE",
6830 true,
6831 static_cast<GLenum>(c.mode),
6832 static_cast<GLsizei>(c.count),
6833 static_cast<GLenum>(c.type),
6834 static_cast<int32>(c.index_offset),
6835 static_cast<GLsizei>(c.primcount));
6838 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6839 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6840 GLuint max_vertex_accessed = 0;
6841 Buffer* buffer = GetBuffer(buffer_id);
6842 if (!buffer) {
6843 // TODO(gman): Should this be a GL error or a command buffer error?
6844 LOCAL_SET_GL_ERROR(
6845 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6846 } else {
6847 if (!buffer->GetMaxValueForRange(
6848 offset, count, type, &max_vertex_accessed)) {
6849 // TODO(gman): Should this be a GL error or a command buffer error?
6850 LOCAL_SET_GL_ERROR(
6851 GL_INVALID_OPERATION,
6852 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6855 return max_vertex_accessed;
6858 // Calls glShaderSource for the various versions of the ShaderSource command.
6859 // Assumes that data / data_size points to a piece of memory that is in range
6860 // of whatever context it came from (shared memory, immediate memory, bucket
6861 // memory.)
6862 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6863 GLuint client_id, const char* data, uint32 data_size) {
6864 std::string str(data, data + data_size);
6865 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6866 if (!shader) {
6867 return error::kNoError;
6869 // Note: We don't actually call glShaderSource here. We wait until
6870 // the call to glCompileShader.
6871 shader->set_source(str);
6872 return error::kNoError;
6875 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6876 uint32 immediate_data_size,
6877 const void* cmd_data) {
6878 const gles2::cmds::ShaderSourceBucket& c =
6879 *static_cast<const gles2::cmds::ShaderSourceBucket*>(cmd_data);
6880 Bucket* bucket = GetBucket(c.data_bucket_id);
6881 if (!bucket || bucket->size() == 0) {
6882 return error::kInvalidArguments;
6884 return ShaderSourceHelper(
6885 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6886 bucket->size() - 1);
6889 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6890 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6891 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6892 if (!shader) {
6893 return;
6895 ShaderTranslator* translator = NULL;
6896 if (use_shader_translator_) {
6897 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6898 vertex_translator_.get() : fragment_translator_.get();
6901 shader->DoCompile(
6902 translator,
6903 feature_info_->feature_flags().angle_translated_shader_source ?
6904 Shader::kANGLE : Shader::kGL);
6906 // CompileShader can be very slow. Exit command processing to allow for
6907 // context preemption and GPU watchdog checks.
6908 ExitCommandProcessingEarly();
6911 void GLES2DecoderImpl::DoGetShaderiv(
6912 GLuint shader_id, GLenum pname, GLint* params) {
6913 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6914 if (!shader) {
6915 return;
6917 switch (pname) {
6918 case GL_SHADER_SOURCE_LENGTH:
6919 *params = shader->source().size();
6920 if (*params)
6921 ++(*params);
6922 return;
6923 case GL_COMPILE_STATUS:
6924 *params = compile_shader_always_succeeds_ ? true : shader->valid();
6925 return;
6926 case GL_INFO_LOG_LENGTH:
6927 *params = shader->log_info().size();
6928 if (*params)
6929 ++(*params);
6930 return;
6931 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6932 *params = shader->translated_source().size();
6933 if (*params)
6934 ++(*params);
6935 return;
6936 default:
6937 break;
6939 glGetShaderiv(shader->service_id(), pname, params);
6942 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
6943 const void* cmd_data) {
6944 const gles2::cmds::GetShaderSource& c =
6945 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
6946 GLuint shader_id = c.shader;
6947 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6948 Bucket* bucket = CreateBucket(bucket_id);
6949 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6950 if (!shader || shader->source().empty()) {
6951 bucket->SetSize(0);
6952 return error::kNoError;
6954 bucket->SetFromString(shader->source().c_str());
6955 return error::kNoError;
6958 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6959 uint32 immediate_data_size,
6960 const void* cmd_data) {
6961 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
6962 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
6963 cmd_data);
6964 GLuint shader_id = c.shader;
6965 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6966 Bucket* bucket = CreateBucket(bucket_id);
6967 Shader* shader = GetShaderInfoNotProgram(
6968 shader_id, "glGetTranslatedShaderSourceANGLE");
6969 if (!shader) {
6970 bucket->SetSize(0);
6971 return error::kNoError;
6974 bucket->SetFromString(shader->translated_source().c_str());
6975 return error::kNoError;
6978 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6979 uint32 immediate_data_size,
6980 const void* cmd_data) {
6981 const gles2::cmds::GetProgramInfoLog& c =
6982 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
6983 GLuint program_id = c.program;
6984 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6985 Bucket* bucket = CreateBucket(bucket_id);
6986 Program* program = GetProgramInfoNotShader(
6987 program_id, "glGetProgramInfoLog");
6988 if (!program || !program->log_info()) {
6989 bucket->SetFromString("");
6990 return error::kNoError;
6992 bucket->SetFromString(program->log_info()->c_str());
6993 return error::kNoError;
6996 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6997 uint32 immediate_data_size,
6998 const void* cmd_data) {
6999 const gles2::cmds::GetShaderInfoLog& c =
7000 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7001 GLuint shader_id = c.shader;
7002 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7003 Bucket* bucket = CreateBucket(bucket_id);
7004 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7005 if (!shader) {
7006 bucket->SetFromString("");
7007 return error::kNoError;
7009 bucket->SetFromString(shader->log_info().c_str());
7010 return error::kNoError;
7013 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7014 return state_.GetEnabled(cap);
7017 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7018 const Buffer* buffer = GetBuffer(client_id);
7019 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7022 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7023 const Framebuffer* framebuffer =
7024 GetFramebuffer(client_id);
7025 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7028 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7029 // IsProgram is true for programs as soon as they are created, until they are
7030 // deleted and no longer in use.
7031 const Program* program = GetProgram(client_id);
7032 return program != NULL && !program->IsDeleted();
7035 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7036 const Renderbuffer* renderbuffer =
7037 GetRenderbuffer(client_id);
7038 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7041 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7042 // IsShader is true for shaders as soon as they are created, until they
7043 // are deleted and not attached to any programs.
7044 const Shader* shader = GetShader(client_id);
7045 return shader != NULL && !shader->IsDeleted();
7048 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7049 const TextureRef* texture_ref = GetTexture(client_id);
7050 return texture_ref && texture_ref->texture()->IsValid();
7053 void GLES2DecoderImpl::DoAttachShader(
7054 GLuint program_client_id, GLint shader_client_id) {
7055 Program* program = GetProgramInfoNotShader(
7056 program_client_id, "glAttachShader");
7057 if (!program) {
7058 return;
7060 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7061 if (!shader) {
7062 return;
7064 if (!program->AttachShader(shader_manager(), shader)) {
7065 LOCAL_SET_GL_ERROR(
7066 GL_INVALID_OPERATION,
7067 "glAttachShader",
7068 "can not attach more than one shader of the same type.");
7069 return;
7071 glAttachShader(program->service_id(), shader->service_id());
7074 void GLES2DecoderImpl::DoDetachShader(
7075 GLuint program_client_id, GLint shader_client_id) {
7076 Program* program = GetProgramInfoNotShader(
7077 program_client_id, "glDetachShader");
7078 if (!program) {
7079 return;
7081 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7082 if (!shader) {
7083 return;
7085 if (!program->DetachShader(shader_manager(), shader)) {
7086 LOCAL_SET_GL_ERROR(
7087 GL_INVALID_OPERATION,
7088 "glDetachShader", "shader not attached to program");
7089 return;
7091 glDetachShader(program->service_id(), shader->service_id());
7094 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7095 Program* program = GetProgramInfoNotShader(
7096 program_client_id, "glValidateProgram");
7097 if (!program) {
7098 return;
7100 program->Validate();
7103 void GLES2DecoderImpl::GetVertexAttribHelper(
7104 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7105 switch (pname) {
7106 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
7107 Buffer* buffer = attrib->buffer();
7108 if (buffer && !buffer->IsDeleted()) {
7109 GLuint client_id;
7110 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7111 *params = client_id;
7113 break;
7115 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7116 *params = attrib->enabled();
7117 break;
7118 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7119 *params = attrib->size();
7120 break;
7121 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7122 *params = attrib->gl_stride();
7123 break;
7124 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7125 *params = attrib->type();
7126 break;
7127 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7128 *params = attrib->normalized();
7129 break;
7130 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7131 *params = attrib->divisor();
7132 break;
7133 default:
7134 NOTREACHED();
7135 break;
7139 void GLES2DecoderImpl::DoGetTexParameterfv(
7140 GLenum target, GLenum pname, GLfloat* params) {
7141 InitTextureMaxAnisotropyIfNeeded(target, pname);
7142 glGetTexParameterfv(target, pname, params);
7145 void GLES2DecoderImpl::DoGetTexParameteriv(
7146 GLenum target, GLenum pname, GLint* params) {
7147 InitTextureMaxAnisotropyIfNeeded(target, pname);
7148 glGetTexParameteriv(target, pname, params);
7151 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7152 GLenum target, GLenum pname) {
7153 if (!workarounds().init_texture_max_anisotropy)
7154 return;
7155 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7156 !validators_->texture_parameter.IsValid(pname)) {
7157 return;
7160 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7161 &state_, target);
7162 if (!texture_ref) {
7163 LOCAL_SET_GL_ERROR(
7164 GL_INVALID_OPERATION,
7165 "glGetTexParamter{fi}v", "unknown texture for target");
7166 return;
7168 Texture* texture = texture_ref->texture();
7169 texture->InitTextureMaxAnisotropyIfNeeded(target);
7172 void GLES2DecoderImpl::DoGetVertexAttribfv(
7173 GLuint index, GLenum pname, GLfloat* params) {
7174 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7175 if (!attrib) {
7176 LOCAL_SET_GL_ERROR(
7177 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7178 return;
7180 switch (pname) {
7181 case GL_CURRENT_VERTEX_ATTRIB: {
7182 const Vec4& value = state_.attrib_values[index];
7183 params[0] = value.v[0];
7184 params[1] = value.v[1];
7185 params[2] = value.v[2];
7186 params[3] = value.v[3];
7187 break;
7189 default: {
7190 GLint value = 0;
7191 GetVertexAttribHelper(attrib, pname, &value);
7192 *params = static_cast<GLfloat>(value);
7193 break;
7198 void GLES2DecoderImpl::DoGetVertexAttribiv(
7199 GLuint index, GLenum pname, GLint* params) {
7200 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7201 if (!attrib) {
7202 LOCAL_SET_GL_ERROR(
7203 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7204 return;
7206 switch (pname) {
7207 case GL_CURRENT_VERTEX_ATTRIB: {
7208 const Vec4& value = state_.attrib_values[index];
7209 params[0] = static_cast<GLint>(value.v[0]);
7210 params[1] = static_cast<GLint>(value.v[1]);
7211 params[2] = static_cast<GLint>(value.v[2]);
7212 params[3] = static_cast<GLint>(value.v[3]);
7213 break;
7215 default:
7216 GetVertexAttribHelper(attrib, pname, params);
7217 break;
7221 bool GLES2DecoderImpl::SetVertexAttribValue(
7222 const char* function_name, GLuint index, const GLfloat* value) {
7223 if (index >= state_.attrib_values.size()) {
7224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7225 return false;
7227 Vec4& v = state_.attrib_values[index];
7228 v.v[0] = value[0];
7229 v.v[1] = value[1];
7230 v.v[2] = value[2];
7231 v.v[3] = value[3];
7232 return true;
7235 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7236 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7237 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7238 glVertexAttrib1f(index, v0);
7242 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7243 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7244 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7245 glVertexAttrib2f(index, v0, v1);
7249 void GLES2DecoderImpl::DoVertexAttrib3f(
7250 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7251 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7252 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7253 glVertexAttrib3f(index, v0, v1, v2);
7257 void GLES2DecoderImpl::DoVertexAttrib4f(
7258 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7259 GLfloat v[4] = { v0, v1, v2, v3, };
7260 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7261 glVertexAttrib4f(index, v0, v1, v2, v3);
7265 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7266 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7267 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7268 glVertexAttrib1fv(index, v);
7272 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7273 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7274 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7275 glVertexAttrib2fv(index, v);
7279 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7280 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7281 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7282 glVertexAttrib3fv(index, v);
7286 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7287 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7288 glVertexAttrib4fv(index, v);
7292 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7293 uint32 immediate_data_size,
7294 const void* cmd_data) {
7295 const gles2::cmds::VertexAttribPointer& c =
7296 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7298 if (!state_.bound_array_buffer.get() ||
7299 state_.bound_array_buffer->IsDeleted()) {
7300 if (state_.vertex_attrib_manager.get() ==
7301 state_.default_vertex_attrib_manager.get()) {
7302 LOCAL_SET_GL_ERROR(
7303 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7304 return error::kNoError;
7305 } else if (c.offset != 0) {
7306 LOCAL_SET_GL_ERROR(
7307 GL_INVALID_VALUE,
7308 "glVertexAttribPointer", "client side arrays are not allowed");
7309 return error::kNoError;
7313 GLuint indx = c.indx;
7314 GLint size = c.size;
7315 GLenum type = c.type;
7316 GLboolean normalized = c.normalized;
7317 GLsizei stride = c.stride;
7318 GLsizei offset = c.offset;
7319 const void* ptr = reinterpret_cast<const void*>(offset);
7320 if (!validators_->vertex_attrib_type.IsValid(type)) {
7321 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7322 return error::kNoError;
7324 if (!validators_->vertex_attrib_size.IsValid(size)) {
7325 LOCAL_SET_GL_ERROR(
7326 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7327 return error::kNoError;
7329 if (indx >= group_->max_vertex_attribs()) {
7330 LOCAL_SET_GL_ERROR(
7331 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7332 return error::kNoError;
7334 if (stride < 0) {
7335 LOCAL_SET_GL_ERROR(
7336 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7337 return error::kNoError;
7339 if (stride > 255) {
7340 LOCAL_SET_GL_ERROR(
7341 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7342 return error::kNoError;
7344 if (offset < 0) {
7345 LOCAL_SET_GL_ERROR(
7346 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7347 return error::kNoError;
7349 GLsizei component_size =
7350 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7351 // component_size must be a power of two to use & as optimized modulo.
7352 DCHECK(GLES2Util::IsPOT(component_size));
7353 if (offset & (component_size - 1)) {
7354 LOCAL_SET_GL_ERROR(
7355 GL_INVALID_OPERATION,
7356 "glVertexAttribPointer", "offset not valid for type");
7357 return error::kNoError;
7359 if (stride & (component_size - 1)) {
7360 LOCAL_SET_GL_ERROR(
7361 GL_INVALID_OPERATION,
7362 "glVertexAttribPointer", "stride not valid for type");
7363 return error::kNoError;
7365 state_.vertex_attrib_manager
7366 ->SetAttribInfo(indx,
7367 state_.bound_array_buffer.get(),
7368 size,
7369 type,
7370 normalized,
7371 stride,
7372 stride != 0 ? stride : component_size * size,
7373 offset);
7374 if (type != GL_FIXED) {
7375 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7377 return error::kNoError;
7380 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7381 GLsizei height) {
7382 state_.viewport_x = x;
7383 state_.viewport_y = y;
7384 state_.viewport_width = std::min(width, viewport_max_width_);
7385 state_.viewport_height = std::min(height, viewport_max_height_);
7386 glViewport(x, y, width, height);
7389 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7390 uint32 immediate_data_size,
7391 const void* cmd_data) {
7392 const gles2::cmds::VertexAttribDivisorANGLE& c =
7393 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
7394 if (!features().angle_instanced_arrays) {
7395 LOCAL_SET_GL_ERROR(
7396 GL_INVALID_OPERATION,
7397 "glVertexAttribDivisorANGLE", "function not available");
7398 return error::kNoError;
7400 GLuint index = c.index;
7401 GLuint divisor = c.divisor;
7402 if (index >= group_->max_vertex_attribs()) {
7403 LOCAL_SET_GL_ERROR(
7404 GL_INVALID_VALUE,
7405 "glVertexAttribDivisorANGLE", "index out of range");
7406 return error::kNoError;
7409 state_.vertex_attrib_manager->SetDivisor(
7410 index,
7411 divisor);
7412 glVertexAttribDivisorANGLE(index, divisor);
7413 return error::kNoError;
7416 template <typename pixel_data_type>
7417 static void WriteAlphaData(
7418 void *pixels, uint32 row_count, uint32 channel_count,
7419 uint32 alpha_channel_index, uint32 unpadded_row_size,
7420 uint32 padded_row_size, pixel_data_type alpha_value) {
7421 DCHECK_GT(channel_count, 0U);
7422 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7423 uint32 unpadded_row_size_in_elements =
7424 unpadded_row_size / sizeof(pixel_data_type);
7425 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7426 uint32 padded_row_size_in_elements =
7427 padded_row_size / sizeof(pixel_data_type);
7428 pixel_data_type* dst =
7429 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7430 for (uint32 yy = 0; yy < row_count; ++yy) {
7431 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7432 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7433 *d = alpha_value;
7435 dst += padded_row_size_in_elements;
7439 void GLES2DecoderImpl::FinishReadPixels(
7440 const cmds::ReadPixels& c,
7441 GLuint buffer) {
7442 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7443 GLsizei width = c.width;
7444 GLsizei height = c.height;
7445 GLenum format = c.format;
7446 GLenum type = c.type;
7447 typedef cmds::ReadPixels::Result Result;
7448 uint32 pixels_size;
7449 Result* result = NULL;
7450 if (c.result_shm_id != 0) {
7451 result = GetSharedMemoryAs<Result*>(
7452 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7453 if (!result) {
7454 if (buffer != 0) {
7455 glDeleteBuffersARB(1, &buffer);
7457 return;
7460 GLES2Util::ComputeImageDataSizes(
7461 width, height, format, type, state_.pack_alignment, &pixels_size,
7462 NULL, NULL);
7463 void* pixels = GetSharedMemoryAs<void*>(
7464 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7465 if (!pixels) {
7466 if (buffer != 0) {
7467 glDeleteBuffersARB(1, &buffer);
7469 return;
7472 if (buffer != 0) {
7473 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7474 void* data;
7475 if (features().map_buffer_range) {
7476 data = glMapBufferRange(
7477 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7478 } else {
7479 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7481 memcpy(pixels, data, pixels_size);
7482 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7483 // have to restore the state.
7484 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7485 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7486 glDeleteBuffersARB(1, &buffer);
7489 if (result != NULL) {
7490 *result = true;
7493 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7494 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7495 if ((channels_exist & 0x0008) == 0 &&
7496 workarounds().clear_alpha_in_readpixels) {
7497 // Set the alpha to 255 because some drivers are buggy in this regard.
7498 uint32 temp_size;
7500 uint32 unpadded_row_size;
7501 uint32 padded_row_size;
7502 if (!GLES2Util::ComputeImageDataSizes(
7503 width, 2, format, type, state_.pack_alignment, &temp_size,
7504 &unpadded_row_size, &padded_row_size)) {
7505 return;
7508 uint32 channel_count = 0;
7509 uint32 alpha_channel = 0;
7510 switch (format) {
7511 case GL_RGBA:
7512 case GL_BGRA_EXT:
7513 channel_count = 4;
7514 alpha_channel = 3;
7515 break;
7516 case GL_ALPHA:
7517 channel_count = 1;
7518 alpha_channel = 0;
7519 break;
7522 if (channel_count > 0) {
7523 switch (type) {
7524 case GL_UNSIGNED_BYTE:
7525 WriteAlphaData<uint8>(
7526 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7527 padded_row_size, 0xFF);
7528 break;
7529 case GL_FLOAT:
7530 WriteAlphaData<float>(
7531 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7532 padded_row_size, 1.0f);
7533 break;
7534 case GL_HALF_FLOAT:
7535 WriteAlphaData<uint16>(
7536 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7537 padded_row_size, 0x3C00);
7538 break;
7544 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
7545 const void* cmd_data) {
7546 const gles2::cmds::ReadPixels& c =
7547 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
7548 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7549 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7550 if (fbo_error != error::kNoError)
7551 return fbo_error;
7552 GLint x = c.x;
7553 GLint y = c.y;
7554 GLsizei width = c.width;
7555 GLsizei height = c.height;
7556 GLenum format = c.format;
7557 GLenum type = c.type;
7558 GLboolean async = c.async;
7559 if (width < 0 || height < 0) {
7560 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7561 return error::kNoError;
7563 typedef cmds::ReadPixels::Result Result;
7564 uint32 pixels_size;
7565 if (!GLES2Util::ComputeImageDataSizes(
7566 width, height, format, type, state_.pack_alignment, &pixels_size,
7567 NULL, NULL)) {
7568 return error::kOutOfBounds;
7570 void* pixels = GetSharedMemoryAs<void*>(
7571 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7572 if (!pixels) {
7573 return error::kOutOfBounds;
7575 Result* result = NULL;
7576 if (c.result_shm_id != 0) {
7577 result = GetSharedMemoryAs<Result*>(
7578 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7579 if (!result) {
7580 return error::kOutOfBounds;
7584 if (!validators_->read_pixel_format.IsValid(format)) {
7585 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7586 return error::kNoError;
7588 if (!validators_->read_pixel_type.IsValid(type)) {
7589 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7590 return error::kNoError;
7592 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7593 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7594 // format and type are acceptable enums but not guaranteed to be supported
7595 // for this framebuffer. Have to ask gl if they are valid.
7596 GLint preferred_format = 0;
7597 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7598 GLint preferred_type = 0;
7599 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7600 if (format != static_cast<GLenum>(preferred_format) ||
7601 type != static_cast<GLenum>(preferred_type)) {
7602 LOCAL_SET_GL_ERROR(
7603 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7604 "with the current read framebuffer");
7605 return error::kNoError;
7608 if (width == 0 || height == 0) {
7609 return error::kNoError;
7612 // Get the size of the current fbo or backbuffer.
7613 gfx::Size max_size = GetBoundReadFrameBufferSize();
7615 int32 max_x;
7616 int32 max_y;
7617 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7618 LOCAL_SET_GL_ERROR(
7619 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7620 return error::kNoError;
7623 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7624 return error::kNoError;
7627 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7628 return error::kNoError;
7631 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7633 ScopedResolvedFrameBufferBinder binder(this, false, true);
7635 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7636 // The user requested an out of range area. Get the results 1 line
7637 // at a time.
7638 uint32 temp_size;
7639 uint32 unpadded_row_size;
7640 uint32 padded_row_size;
7641 if (!GLES2Util::ComputeImageDataSizes(
7642 width, 2, format, type, state_.pack_alignment, &temp_size,
7643 &unpadded_row_size, &padded_row_size)) {
7644 LOCAL_SET_GL_ERROR(
7645 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7646 return error::kNoError;
7649 GLint dest_x_offset = std::max(-x, 0);
7650 uint32 dest_row_offset;
7651 if (!GLES2Util::ComputeImageDataSizes(
7652 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7653 NULL, NULL)) {
7654 LOCAL_SET_GL_ERROR(
7655 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7656 return error::kNoError;
7659 // Copy each row into the larger dest rect.
7660 int8* dst = static_cast<int8*>(pixels);
7661 GLint read_x = std::max(0, x);
7662 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7663 GLint read_width = read_end_x - read_x;
7664 for (GLint yy = 0; yy < height; ++yy) {
7665 GLint ry = y + yy;
7667 // Clear the row.
7668 memset(dst, 0, unpadded_row_size);
7670 // If the row is in range, copy it.
7671 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7672 glReadPixels(
7673 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7675 dst += padded_row_size;
7677 } else {
7678 if (async && features().use_async_readpixels) {
7679 GLuint buffer;
7680 glGenBuffersARB(1, &buffer);
7681 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7682 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7683 GLenum error = glGetError();
7684 if (error == GL_NO_ERROR) {
7685 glReadPixels(x, y, width, height, format, type, 0);
7686 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7687 new FenceCallback()));
7688 WaitForReadPixels(base::Bind(
7689 &GLES2DecoderImpl::FinishReadPixels,
7690 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7691 <GLES2DecoderImpl>(this),
7692 c, buffer));
7693 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7694 return error::kNoError;
7695 } else {
7696 // On error, unbind pack buffer and fall through to sync readpixels
7697 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7700 glReadPixels(x, y, width, height, format, type, pixels);
7702 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7703 if (error == GL_NO_ERROR) {
7704 if (result != NULL) {
7705 *result = true;
7707 FinishReadPixels(c, 0);
7710 return error::kNoError;
7713 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
7714 const void* cmd_data) {
7715 const gles2::cmds::PixelStorei& c =
7716 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
7717 GLenum pname = c.pname;
7718 GLenum param = c.param;
7719 if (!validators_->pixel_store.IsValid(pname)) {
7720 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7721 return error::kNoError;
7723 switch (pname) {
7724 case GL_PACK_ALIGNMENT:
7725 case GL_UNPACK_ALIGNMENT:
7726 if (!validators_->pixel_store_alignment.IsValid(param)) {
7727 LOCAL_SET_GL_ERROR(
7728 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7729 return error::kNoError;
7731 break;
7732 case GL_UNPACK_FLIP_Y_CHROMIUM:
7733 unpack_flip_y_ = (param != 0);
7734 return error::kNoError;
7735 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7736 unpack_premultiply_alpha_ = (param != 0);
7737 return error::kNoError;
7738 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7739 unpack_unpremultiply_alpha_ = (param != 0);
7740 return error::kNoError;
7741 default:
7742 break;
7744 glPixelStorei(pname, param);
7745 switch (pname) {
7746 case GL_PACK_ALIGNMENT:
7747 state_.pack_alignment = param;
7748 break;
7749 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7750 state_.pack_reverse_row_order = (param != 0);
7751 break;
7752 case GL_UNPACK_ALIGNMENT:
7753 state_.unpack_alignment = param;
7754 break;
7755 default:
7756 // Validation should have prevented us from getting here.
7757 NOTREACHED();
7758 break;
7760 return error::kNoError;
7763 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7764 uint32 immediate_data_size,
7765 const void* cmd_data) {
7766 const gles2::cmds::PostSubBufferCHROMIUM& c =
7767 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
7768 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7770 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7772 if (!supports_post_sub_buffer_) {
7773 LOCAL_SET_GL_ERROR(
7774 GL_INVALID_OPERATION,
7775 "glPostSubBufferCHROMIUM", "command not supported by surface");
7776 return error::kNoError;
7778 bool is_tracing;
7779 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7780 &is_tracing);
7781 if (is_tracing) {
7782 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7783 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7784 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7785 is_offscreen ? offscreen_size_ : surface_->GetSize());
7787 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7788 return error::kNoError;
7789 } else {
7790 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7791 return error::kLostContext;
7795 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7796 uint32 immediate_data_size,
7797 const void* cmd_data) {
7798 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
7799 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
7800 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
7801 if (!ref) {
7802 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
7803 "glScheduleOverlayPlaneCHROMIUM",
7804 "unknown texture");
7805 return error::kNoError;
7807 gfx::GLImage* image =
7808 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
7809 if (!image) {
7810 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
7811 "glScheduleOverlayPlaneCHROMIUM",
7812 "unsupported texture format");
7813 return error::kNoError;
7815 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
7816 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
7817 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
7818 "glScheduleOverlayPlaneCHROMIUM",
7819 "invalid transform enum");
7820 return error::kNoError;
7822 if (!surface_->ScheduleOverlayPlane(
7823 c.plane_z_order,
7824 transform,
7825 image,
7826 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
7827 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
7828 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
7829 "glScheduleOverlayPlaneCHROMIUM",
7830 "failed to schedule overlay");
7832 return error::kNoError;
7835 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7836 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7837 const std::string& name_str) {
7838 if (!StringIsValidForGLES(name_str.c_str())) {
7839 LOCAL_SET_GL_ERROR(
7840 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7841 return error::kNoError;
7843 Program* program = GetProgramInfoNotShader(
7844 client_id, "glGetAttribLocation");
7845 if (!program) {
7846 return error::kNoError;
7848 if (!program->IsValid()) {
7849 LOCAL_SET_GL_ERROR(
7850 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7851 return error::kNoError;
7853 GLint* location = GetSharedMemoryAs<GLint*>(
7854 location_shm_id, location_shm_offset, sizeof(GLint));
7855 if (!location) {
7856 return error::kOutOfBounds;
7858 // Require the client to init this incase the context is lost and we are no
7859 // longer executing commands.
7860 if (*location != -1) {
7861 return error::kGenericError;
7863 *location = program->GetAttribLocation(name_str);
7864 return error::kNoError;
7867 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7868 uint32 immediate_data_size,
7869 const void* cmd_data) {
7870 const gles2::cmds::GetAttribLocation& c =
7871 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
7872 Bucket* bucket = GetBucket(c.name_bucket_id);
7873 if (!bucket) {
7874 return error::kInvalidArguments;
7876 std::string name_str;
7877 if (!bucket->GetAsString(&name_str)) {
7878 return error::kInvalidArguments;
7880 return GetAttribLocationHelper(
7881 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7884 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7885 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7886 const std::string& name_str) {
7887 if (!StringIsValidForGLES(name_str.c_str())) {
7888 LOCAL_SET_GL_ERROR(
7889 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7890 return error::kNoError;
7892 Program* program = GetProgramInfoNotShader(
7893 client_id, "glGetUniformLocation");
7894 if (!program) {
7895 return error::kNoError;
7897 if (!program->IsValid()) {
7898 LOCAL_SET_GL_ERROR(
7899 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7900 return error::kNoError;
7902 GLint* location = GetSharedMemoryAs<GLint*>(
7903 location_shm_id, location_shm_offset, sizeof(GLint));
7904 if (!location) {
7905 return error::kOutOfBounds;
7907 // Require the client to init this incase the context is lost an we are no
7908 // longer executing commands.
7909 if (*location != -1) {
7910 return error::kGenericError;
7912 *location = program->GetUniformFakeLocation(name_str);
7913 return error::kNoError;
7916 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7917 uint32 immediate_data_size,
7918 const void* cmd_data) {
7919 const gles2::cmds::GetUniformLocation& c =
7920 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
7921 Bucket* bucket = GetBucket(c.name_bucket_id);
7922 if (!bucket) {
7923 return error::kInvalidArguments;
7925 std::string name_str;
7926 if (!bucket->GetAsString(&name_str)) {
7927 return error::kInvalidArguments;
7929 return GetUniformLocationHelper(
7930 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7933 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
7934 const void* cmd_data) {
7935 const gles2::cmds::GetString& c =
7936 *static_cast<const gles2::cmds::GetString*>(cmd_data);
7937 GLenum name = static_cast<GLenum>(c.name);
7938 if (!validators_->string_type.IsValid(name)) {
7939 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7940 return error::kNoError;
7942 const char* str = reinterpret_cast<const char*>(glGetString(name));
7943 std::string extensions;
7944 switch (name) {
7945 case GL_VERSION:
7946 str = "OpenGL ES 2.0 Chromium";
7947 break;
7948 case GL_SHADING_LANGUAGE_VERSION:
7949 str = "OpenGL ES GLSL ES 1.0 Chromium";
7950 break;
7951 case GL_RENDERER:
7952 case GL_VENDOR:
7953 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7954 // They are used by WEBGL_debug_renderer_info.
7955 if (!force_webgl_glsl_validation_)
7956 str = "Chromium";
7957 break;
7958 case GL_EXTENSIONS:
7960 // For WebGL contexts, strip out the OES derivatives and
7961 // EXT frag depth extensions if they have not been enabled.
7962 if (force_webgl_glsl_validation_) {
7963 extensions = feature_info_->extensions();
7964 if (!derivatives_explicitly_enabled_) {
7965 size_t offset = extensions.find(kOESDerivativeExtension);
7966 if (std::string::npos != offset) {
7967 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7968 std::string());
7971 if (!frag_depth_explicitly_enabled_) {
7972 size_t offset = extensions.find(kEXTFragDepthExtension);
7973 if (std::string::npos != offset) {
7974 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7975 std::string());
7978 if (!draw_buffers_explicitly_enabled_) {
7979 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7980 if (std::string::npos != offset) {
7981 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7982 std::string());
7985 if (!shader_texture_lod_explicitly_enabled_) {
7986 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
7987 if (std::string::npos != offset) {
7988 extensions.replace(offset,
7989 arraysize(kEXTShaderTextureLodExtension),
7990 std::string());
7993 } else {
7994 extensions = feature_info_->extensions().c_str();
7996 if (supports_post_sub_buffer_)
7997 extensions += " GL_CHROMIUM_post_sub_buffer";
7998 str = extensions.c_str();
8000 break;
8001 default:
8002 break;
8004 Bucket* bucket = CreateBucket(c.bucket_id);
8005 bucket->SetFromString(str);
8006 return error::kNoError;
8009 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8010 const void* cmd_data) {
8011 const gles2::cmds::BufferData& c =
8012 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8013 GLenum target = static_cast<GLenum>(c.target);
8014 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8015 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8016 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8017 GLenum usage = static_cast<GLenum>(c.usage);
8018 const void* data = NULL;
8019 if (data_shm_id != 0 || data_shm_offset != 0) {
8020 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8021 if (!data) {
8022 return error::kOutOfBounds;
8025 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8026 return error::kNoError;
8029 void GLES2DecoderImpl::DoBufferSubData(
8030 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8031 // Just delegate it. Some validation is actually done before this.
8032 buffer_manager()->ValidateAndDoBufferSubData(
8033 &state_, target, offset, size, data);
8036 bool GLES2DecoderImpl::ClearLevel(
8037 unsigned service_id,
8038 unsigned bind_target,
8039 unsigned target,
8040 int level,
8041 unsigned internal_format,
8042 unsigned format,
8043 unsigned type,
8044 int width,
8045 int height,
8046 bool is_texture_immutable) {
8047 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8048 if (feature_info_->feature_flags().angle_depth_texture &&
8049 (channels & GLES2Util::kDepth) != 0) {
8050 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8051 // on depth formats.
8052 GLuint fb = 0;
8053 glGenFramebuffersEXT(1, &fb);
8054 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8056 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8057 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8058 GL_DEPTH_ATTACHMENT;
8060 glFramebufferTexture2DEXT(
8061 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
8062 // ANGLE promises a depth only attachment ok.
8063 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8064 GL_FRAMEBUFFER_COMPLETE) {
8065 return false;
8067 glClearStencil(0);
8068 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8069 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8070 glClearDepth(1.0f);
8071 state_.SetDeviceDepthMask(GL_TRUE);
8072 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8073 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8075 RestoreClearState();
8077 glDeleteFramebuffersEXT(1, &fb);
8078 Framebuffer* framebuffer =
8079 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8080 GLuint fb_service_id =
8081 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8082 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8083 return true;
8086 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8088 uint32 size;
8089 uint32 padded_row_size;
8090 if (!GLES2Util::ComputeImageDataSizes(
8091 width, height, format, type, state_.unpack_alignment, &size,
8092 NULL, &padded_row_size)) {
8093 return false;
8096 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8098 int tile_height;
8100 if (size > kMaxZeroSize) {
8101 if (kMaxZeroSize < padded_row_size) {
8102 // That'd be an awfully large texture.
8103 return false;
8105 // We should never have a large total size with a zero row size.
8106 DCHECK_GT(padded_row_size, 0U);
8107 tile_height = kMaxZeroSize / padded_row_size;
8108 if (!GLES2Util::ComputeImageDataSizes(
8109 width, tile_height, format, type, state_.unpack_alignment, &size,
8110 NULL, NULL)) {
8111 return false;
8113 } else {
8114 tile_height = height;
8117 // Assumes the size has already been checked.
8118 scoped_ptr<char[]> zero(new char[size]);
8119 memset(zero.get(), 0, size);
8120 glBindTexture(bind_target, service_id);
8122 GLint y = 0;
8123 while (y < height) {
8124 GLint h = y + tile_height > height ? height - y : tile_height;
8125 if (is_texture_immutable || h != height) {
8126 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8127 } else {
8128 glTexImage2D(
8129 target, level, internal_format, width, h, 0, format, type,
8130 zero.get());
8132 y += tile_height;
8134 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
8135 &state_, bind_target);
8136 glBindTexture(bind_target, texture ? texture->service_id() : 0);
8137 return true;
8140 namespace {
8142 const int kS3TCBlockWidth = 4;
8143 const int kS3TCBlockHeight = 4;
8144 const int kS3TCDXT1BlockSize = 8;
8145 const int kS3TCDXT3AndDXT5BlockSize = 16;
8147 bool IsValidDXTSize(GLint level, GLsizei size) {
8148 return (size == 1) ||
8149 (size == 2) || !(size % kS3TCBlockWidth);
8152 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8153 return GLES2Util::IsPOT(size);
8156 } // anonymous namespace.
8158 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8159 const char* function_name,
8160 GLsizei width, GLsizei height, GLenum format, size_t size) {
8161 unsigned int bytes_required = 0;
8163 switch (format) {
8164 case GL_ATC_RGB_AMD:
8165 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8166 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8167 case GL_ETC1_RGB8_OES: {
8168 int num_blocks_across =
8169 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8170 int num_blocks_down =
8171 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8172 int num_blocks = num_blocks_across * num_blocks_down;
8173 bytes_required = num_blocks * kS3TCDXT1BlockSize;
8174 break;
8176 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8177 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8178 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8179 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8180 int num_blocks_across =
8181 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8182 int num_blocks_down =
8183 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8184 int num_blocks = num_blocks_across * num_blocks_down;
8185 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
8186 break;
8188 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8189 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
8190 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
8191 break;
8193 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8194 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8195 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
8196 break;
8198 default:
8199 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8200 return false;
8203 if (size != bytes_required) {
8204 LOCAL_SET_GL_ERROR(
8205 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8206 return false;
8209 return true;
8212 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8213 const char* function_name,
8214 GLint level, GLsizei width, GLsizei height, GLenum format) {
8215 switch (format) {
8216 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8217 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8218 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8219 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8220 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8221 LOCAL_SET_GL_ERROR(
8222 GL_INVALID_OPERATION, function_name,
8223 "width or height invalid for level");
8224 return false;
8226 return true;
8228 case GL_ATC_RGB_AMD:
8229 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8230 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8231 case GL_ETC1_RGB8_OES: {
8232 if (width <= 0 || height <= 0) {
8233 LOCAL_SET_GL_ERROR(
8234 GL_INVALID_OPERATION, function_name,
8235 "width or height invalid for level");
8236 return false;
8238 return true;
8240 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8241 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8242 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8243 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8244 if (!IsValidPVRTCSize(level, width) ||
8245 !IsValidPVRTCSize(level, height)) {
8246 LOCAL_SET_GL_ERROR(
8247 GL_INVALID_OPERATION, function_name,
8248 "width or height invalid for level");
8249 return false;
8251 return true;
8253 default:
8254 return false;
8258 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8259 const char* function_name,
8260 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8261 GLsizei width, GLsizei height, GLenum format,
8262 Texture* texture) {
8263 if (xoffset < 0 || yoffset < 0) {
8264 LOCAL_SET_GL_ERROR(
8265 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8266 return false;
8269 switch (format) {
8270 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8271 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8272 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8273 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8274 const int kBlockWidth = 4;
8275 const int kBlockHeight = 4;
8276 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8277 LOCAL_SET_GL_ERROR(
8278 GL_INVALID_OPERATION, function_name,
8279 "xoffset or yoffset not multiple of 4");
8280 return false;
8282 GLsizei tex_width = 0;
8283 GLsizei tex_height = 0;
8284 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8285 width - xoffset > tex_width ||
8286 height - yoffset > tex_height) {
8287 LOCAL_SET_GL_ERROR(
8288 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8289 return false;
8291 return ValidateCompressedTexDimensions(
8292 function_name, level, width, height, format);
8294 case GL_ATC_RGB_AMD:
8295 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8296 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8297 LOCAL_SET_GL_ERROR(
8298 GL_INVALID_OPERATION, function_name,
8299 "not supported for ATC textures");
8300 return false;
8302 case GL_ETC1_RGB8_OES: {
8303 LOCAL_SET_GL_ERROR(
8304 GL_INVALID_OPERATION, function_name,
8305 "not supported for ECT1_RGB8_OES textures");
8306 return false;
8308 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8309 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8310 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8311 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8312 if ((xoffset != 0) || (yoffset != 0)) {
8313 LOCAL_SET_GL_ERROR(
8314 GL_INVALID_OPERATION, function_name,
8315 "xoffset and yoffset must be zero");
8316 return false;
8318 GLsizei tex_width = 0;
8319 GLsizei tex_height = 0;
8320 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8321 width != tex_width ||
8322 height != tex_height) {
8323 LOCAL_SET_GL_ERROR(
8324 GL_INVALID_OPERATION, function_name,
8325 "dimensions must match existing texture level dimensions");
8326 return false;
8328 return ValidateCompressedTexDimensions(
8329 function_name, level, width, height, format);
8331 default:
8332 return false;
8336 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8337 GLenum target,
8338 GLint level,
8339 GLenum internal_format,
8340 GLsizei width,
8341 GLsizei height,
8342 GLint border,
8343 GLsizei image_size,
8344 const void* data) {
8345 // TODO(gman): Validate image_size is correct for width, height and format.
8346 if (!validators_->texture_target.IsValid(target)) {
8347 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8348 "glCompressedTexImage2D", target, "target");
8349 return error::kNoError;
8351 if (!validators_->compressed_texture_format.IsValid(
8352 internal_format)) {
8353 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8354 "glCompressedTexImage2D", internal_format, "internal_format");
8355 return error::kNoError;
8357 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8358 border != 0) {
8359 LOCAL_SET_GL_ERROR(
8360 GL_INVALID_VALUE,
8361 "glCompressedTexImage2D", "dimensions out of range");
8362 return error::kNoError;
8364 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8365 &state_, target);
8366 if (!texture_ref) {
8367 LOCAL_SET_GL_ERROR(
8368 GL_INVALID_VALUE,
8369 "glCompressedTexImage2D", "unknown texture target");
8370 return error::kNoError;
8372 Texture* texture = texture_ref->texture();
8373 if (texture->IsImmutable()) {
8374 LOCAL_SET_GL_ERROR(
8375 GL_INVALID_OPERATION,
8376 "glCompressedTexImage2D", "texture is immutable");
8377 return error::kNoError;
8380 if (!ValidateCompressedTexDimensions(
8381 "glCompressedTexImage2D", level, width, height, internal_format) ||
8382 !ValidateCompressedTexFuncData(
8383 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8384 return error::kNoError;
8387 if (!EnsureGPUMemoryAvailable(image_size)) {
8388 LOCAL_SET_GL_ERROR(
8389 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8390 return error::kNoError;
8393 if (texture->IsAttachedToFramebuffer()) {
8394 framebuffer_state_.clear_state_dirty = true;
8397 scoped_ptr<int8[]> zero;
8398 if (!data) {
8399 zero.reset(new int8[image_size]);
8400 memset(zero.get(), 0, image_size);
8401 data = zero.get();
8403 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8404 glCompressedTexImage2D(
8405 target, level, internal_format, width, height, border, image_size, data);
8406 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8407 if (error == GL_NO_ERROR) {
8408 texture_manager()->SetLevelInfo(
8409 texture_ref, target, level, internal_format,
8410 width, height, 1, border, 0, 0, true);
8413 // This may be a slow command. Exit command processing to allow for
8414 // context preemption and GPU watchdog checks.
8415 ExitCommandProcessingEarly();
8416 return error::kNoError;
8419 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8420 uint32 immediate_data_size,
8421 const void* cmd_data) {
8422 const gles2::cmds::CompressedTexImage2D& c =
8423 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
8424 GLenum target = static_cast<GLenum>(c.target);
8425 GLint level = static_cast<GLint>(c.level);
8426 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8427 GLsizei width = static_cast<GLsizei>(c.width);
8428 GLsizei height = static_cast<GLsizei>(c.height);
8429 GLint border = static_cast<GLint>(c.border);
8430 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8431 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8432 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8433 const void* data = NULL;
8434 if (data_shm_id != 0 || data_shm_offset != 0) {
8435 data = GetSharedMemoryAs<const void*>(
8436 data_shm_id, data_shm_offset, image_size);
8437 if (!data) {
8438 return error::kOutOfBounds;
8441 return DoCompressedTexImage2D(
8442 target, level, internal_format, width, height, border, image_size, data);
8445 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8446 uint32 immediate_data_size,
8447 const void* cmd_data) {
8448 const gles2::cmds::CompressedTexImage2DBucket& c =
8449 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
8450 GLenum target = static_cast<GLenum>(c.target);
8451 GLint level = static_cast<GLint>(c.level);
8452 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8453 GLsizei width = static_cast<GLsizei>(c.width);
8454 GLsizei height = static_cast<GLsizei>(c.height);
8455 GLint border = static_cast<GLint>(c.border);
8456 Bucket* bucket = GetBucket(c.bucket_id);
8457 if (!bucket) {
8458 return error::kInvalidArguments;
8460 uint32 data_size = bucket->size();
8461 GLsizei imageSize = data_size;
8462 const void* data = bucket->GetData(0, data_size);
8463 if (!data) {
8464 return error::kInvalidArguments;
8466 return DoCompressedTexImage2D(
8467 target, level, internal_format, width, height, border,
8468 imageSize, data);
8471 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8472 uint32 immediate_data_size,
8473 const void* cmd_data) {
8474 const gles2::cmds::CompressedTexSubImage2DBucket& c =
8475 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
8476 GLenum target = static_cast<GLenum>(c.target);
8477 GLint level = static_cast<GLint>(c.level);
8478 GLint xoffset = static_cast<GLint>(c.xoffset);
8479 GLint yoffset = static_cast<GLint>(c.yoffset);
8480 GLsizei width = static_cast<GLsizei>(c.width);
8481 GLsizei height = static_cast<GLsizei>(c.height);
8482 GLenum format = static_cast<GLenum>(c.format);
8483 Bucket* bucket = GetBucket(c.bucket_id);
8484 if (!bucket) {
8485 return error::kInvalidArguments;
8487 uint32 data_size = bucket->size();
8488 GLsizei imageSize = data_size;
8489 const void* data = bucket->GetData(0, data_size);
8490 if (!data) {
8491 return error::kInvalidArguments;
8493 if (!validators_->texture_target.IsValid(target)) {
8494 LOCAL_SET_GL_ERROR(
8495 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8496 return error::kNoError;
8498 if (!validators_->compressed_texture_format.IsValid(format)) {
8499 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8500 "glCompressedTexSubImage2D", format, "format");
8501 return error::kNoError;
8503 if (width < 0) {
8504 LOCAL_SET_GL_ERROR(
8505 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8506 return error::kNoError;
8508 if (height < 0) {
8509 LOCAL_SET_GL_ERROR(
8510 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8511 return error::kNoError;
8513 if (imageSize < 0) {
8514 LOCAL_SET_GL_ERROR(
8515 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8516 return error::kNoError;
8518 DoCompressedTexSubImage2D(
8519 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8520 return error::kNoError;
8523 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
8524 const void* cmd_data) {
8525 const gles2::cmds::TexImage2D& c =
8526 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
8527 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8528 "width", c.width, "height", c.height);
8529 // Set as failed for now, but if it successed, this will be set to not failed.
8530 texture_state_.tex_image_2d_failed = true;
8531 GLenum target = static_cast<GLenum>(c.target);
8532 GLint level = static_cast<GLint>(c.level);
8533 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8534 // for internalformat.
8535 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8536 GLsizei width = static_cast<GLsizei>(c.width);
8537 GLsizei height = static_cast<GLsizei>(c.height);
8538 GLint border = static_cast<GLint>(c.border);
8539 GLenum format = static_cast<GLenum>(c.format);
8540 GLenum type = static_cast<GLenum>(c.type);
8541 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8542 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8543 uint32 pixels_size;
8544 if (!GLES2Util::ComputeImageDataSizes(
8545 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8546 NULL)) {
8547 return error::kOutOfBounds;
8549 const void* pixels = NULL;
8550 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8551 pixels = GetSharedMemoryAs<const void*>(
8552 pixels_shm_id, pixels_shm_offset, pixels_size);
8553 if (!pixels) {
8554 return error::kOutOfBounds;
8558 TextureManager::DoTextImage2DArguments args = {
8559 target, level, internal_format, width, height, border, format, type,
8560 pixels, pixels_size};
8561 texture_manager()->ValidateAndDoTexImage2D(
8562 &texture_state_, &state_, &framebuffer_state_, args);
8564 // This may be a slow command. Exit command processing to allow for
8565 // context preemption and GPU watchdog checks.
8566 ExitCommandProcessingEarly();
8567 return error::kNoError;
8570 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8571 GLenum target,
8572 GLint level,
8573 GLint xoffset,
8574 GLint yoffset,
8575 GLsizei width,
8576 GLsizei height,
8577 GLenum format,
8578 GLsizei image_size,
8579 const void * data) {
8580 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8581 &state_, target);
8582 if (!texture_ref) {
8583 LOCAL_SET_GL_ERROR(
8584 GL_INVALID_OPERATION,
8585 "glCompressedTexSubImage2D", "unknown texture for target");
8586 return;
8588 Texture* texture = texture_ref->texture();
8589 GLenum type = 0;
8590 GLenum internal_format = 0;
8591 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8592 LOCAL_SET_GL_ERROR(
8593 GL_INVALID_OPERATION,
8594 "glCompressedTexSubImage2D", "level does not exist.");
8595 return;
8597 if (internal_format != format) {
8598 LOCAL_SET_GL_ERROR(
8599 GL_INVALID_OPERATION,
8600 "glCompressedTexSubImage2D", "format does not match internal format.");
8601 return;
8603 if (!texture->ValidForTexture(
8604 target, level, xoffset, yoffset, width, height, type)) {
8605 LOCAL_SET_GL_ERROR(
8606 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8607 return;
8610 if (!ValidateCompressedTexFuncData(
8611 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8612 !ValidateCompressedTexSubDimensions(
8613 "glCompressedTexSubImage2D",
8614 target, level, xoffset, yoffset, width, height, format, texture)) {
8615 return;
8619 // Note: There is no need to deal with texture cleared tracking here
8620 // because the validation above means you can only get here if the level
8621 // is already a matching compressed format and in that case
8622 // CompressedTexImage2D already cleared the texture.
8623 glCompressedTexSubImage2D(
8624 target, level, xoffset, yoffset, width, height, format, image_size, data);
8626 // This may be a slow command. Exit command processing to allow for
8627 // context preemption and GPU watchdog checks.
8628 ExitCommandProcessingEarly();
8631 static void Clip(
8632 GLint start, GLint range, GLint sourceRange,
8633 GLint* out_start, GLint* out_range) {
8634 DCHECK(out_start);
8635 DCHECK(out_range);
8636 if (start < 0) {
8637 range += start;
8638 start = 0;
8640 GLint end = start + range;
8641 if (end > sourceRange) {
8642 range -= end - sourceRange;
8644 *out_start = start;
8645 *out_range = range;
8648 void GLES2DecoderImpl::DoCopyTexImage2D(
8649 GLenum target,
8650 GLint level,
8651 GLenum internal_format,
8652 GLint x,
8653 GLint y,
8654 GLsizei width,
8655 GLsizei height,
8656 GLint border) {
8657 DCHECK(!ShouldDeferReads());
8658 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8659 &state_, target);
8660 if (!texture_ref) {
8661 LOCAL_SET_GL_ERROR(
8662 GL_INVALID_OPERATION,
8663 "glCopyTexImage2D", "unknown texture for target");
8664 return;
8666 Texture* texture = texture_ref->texture();
8667 if (texture->IsImmutable()) {
8668 LOCAL_SET_GL_ERROR(
8669 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8670 return;
8672 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8673 border != 0) {
8674 LOCAL_SET_GL_ERROR(
8675 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8676 return;
8678 if (!texture_manager()->ValidateFormatAndTypeCombination(
8679 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8680 GL_UNSIGNED_BYTE)) {
8681 return;
8684 // Check we have compatible formats.
8685 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8686 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8687 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8689 if ((channels_needed & channels_exist) != channels_needed) {
8690 LOCAL_SET_GL_ERROR(
8691 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8692 return;
8695 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8696 LOCAL_SET_GL_ERROR(
8697 GL_INVALID_OPERATION,
8698 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8699 return;
8702 uint32 estimated_size = 0;
8703 if (!GLES2Util::ComputeImageDataSizes(
8704 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8705 &estimated_size, NULL, NULL)) {
8706 LOCAL_SET_GL_ERROR(
8707 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8708 return;
8711 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8712 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8713 return;
8716 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
8717 return;
8720 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8721 return;
8724 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8725 ScopedResolvedFrameBufferBinder binder(this, false, true);
8726 gfx::Size size = GetBoundReadFrameBufferSize();
8728 if (texture->IsAttachedToFramebuffer()) {
8729 framebuffer_state_.clear_state_dirty = true;
8732 // Clip to size to source dimensions
8733 GLint copyX = 0;
8734 GLint copyY = 0;
8735 GLint copyWidth = 0;
8736 GLint copyHeight = 0;
8737 Clip(x, width, size.width(), &copyX, &copyWidth);
8738 Clip(y, height, size.height(), &copyY, &copyHeight);
8740 if (copyX != x ||
8741 copyY != y ||
8742 copyWidth != width ||
8743 copyHeight != height) {
8744 // some part was clipped so clear the texture.
8745 if (!ClearLevel(
8746 texture->service_id(), texture->target(),
8747 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8748 width, height, texture->IsImmutable())) {
8749 LOCAL_SET_GL_ERROR(
8750 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8751 return;
8753 if (copyHeight > 0 && copyWidth > 0) {
8754 GLint dx = copyX - x;
8755 GLint dy = copyY - y;
8756 GLint destX = dx;
8757 GLint destY = dy;
8758 ScopedModifyPixels modify(texture_ref);
8759 glCopyTexSubImage2D(target, level,
8760 destX, destY, copyX, copyY,
8761 copyWidth, copyHeight);
8763 } else {
8764 ScopedModifyPixels modify(texture_ref);
8765 glCopyTexImage2D(target, level, internal_format,
8766 copyX, copyY, copyWidth, copyHeight, border);
8768 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8769 if (error == GL_NO_ERROR) {
8770 texture_manager()->SetLevelInfo(
8771 texture_ref, target, level, internal_format, width, height, 1,
8772 border, internal_format, GL_UNSIGNED_BYTE, true);
8775 // This may be a slow command. Exit command processing to allow for
8776 // context preemption and GPU watchdog checks.
8777 ExitCommandProcessingEarly();
8780 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8781 GLenum target,
8782 GLint level,
8783 GLint xoffset,
8784 GLint yoffset,
8785 GLint x,
8786 GLint y,
8787 GLsizei width,
8788 GLsizei height) {
8789 DCHECK(!ShouldDeferReads());
8790 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8791 &state_, target);
8792 if (!texture_ref) {
8793 LOCAL_SET_GL_ERROR(
8794 GL_INVALID_OPERATION,
8795 "glCopyTexSubImage2D", "unknown texture for target");
8796 return;
8798 Texture* texture = texture_ref->texture();
8799 GLenum type = 0;
8800 GLenum format = 0;
8801 if (!texture->GetLevelType(target, level, &type, &format) ||
8802 !texture->ValidForTexture(
8803 target, level, xoffset, yoffset, width, height, type)) {
8804 LOCAL_SET_GL_ERROR(
8805 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8806 return;
8808 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8809 LOCAL_SET_GL_ERROR(
8810 GL_INVALID_OPERATION,
8811 "glCopyTexSubImage2D", "async upload pending for texture");
8812 return;
8815 // Check we have compatible formats.
8816 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8817 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8818 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8820 if (!channels_needed ||
8821 (channels_needed & channels_exist) != channels_needed) {
8822 LOCAL_SET_GL_ERROR(
8823 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8824 return;
8827 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8828 LOCAL_SET_GL_ERROR(
8829 GL_INVALID_OPERATION,
8830 "glCopySubImage2D", "can not be used with depth or stencil textures");
8831 return;
8834 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
8835 return;
8838 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8839 return;
8842 ScopedResolvedFrameBufferBinder binder(this, false, true);
8843 gfx::Size size = GetBoundReadFrameBufferSize();
8844 GLint copyX = 0;
8845 GLint copyY = 0;
8846 GLint copyWidth = 0;
8847 GLint copyHeight = 0;
8848 Clip(x, width, size.width(), &copyX, &copyWidth);
8849 Clip(y, height, size.height(), &copyY, &copyHeight);
8851 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8852 LOCAL_SET_GL_ERROR(
8853 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8854 return;
8857 if (copyX != x ||
8858 copyY != y ||
8859 copyWidth != width ||
8860 copyHeight != height) {
8861 // some part was clipped so clear the sub rect.
8862 uint32 pixels_size = 0;
8863 if (!GLES2Util::ComputeImageDataSizes(
8864 width, height, format, type, state_.unpack_alignment, &pixels_size,
8865 NULL, NULL)) {
8866 LOCAL_SET_GL_ERROR(
8867 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8868 return;
8870 scoped_ptr<char[]> zero(new char[pixels_size]);
8871 memset(zero.get(), 0, pixels_size);
8872 ScopedModifyPixels modify(texture_ref);
8873 glTexSubImage2D(
8874 target, level, xoffset, yoffset, width, height,
8875 format, type, zero.get());
8878 if (copyHeight > 0 && copyWidth > 0) {
8879 GLint dx = copyX - x;
8880 GLint dy = copyY - y;
8881 GLint destX = xoffset + dx;
8882 GLint destY = yoffset + dy;
8883 ScopedModifyPixels modify(texture_ref);
8884 glCopyTexSubImage2D(target, level,
8885 destX, destY, copyX, copyY,
8886 copyWidth, copyHeight);
8889 // This may be a slow command. Exit command processing to allow for
8890 // context preemption and GPU watchdog checks.
8891 ExitCommandProcessingEarly();
8894 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8895 error::Error* error,
8896 const char* function_name,
8897 GLenum target,
8898 GLint level,
8899 GLint xoffset,
8900 GLint yoffset,
8901 GLsizei width,
8902 GLsizei height,
8903 GLenum format,
8904 GLenum type,
8905 const void * data) {
8906 (*error) = error::kNoError;
8907 if (!validators_->texture_target.IsValid(target)) {
8908 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8909 return false;
8911 if (width < 0) {
8912 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8913 return false;
8915 if (height < 0) {
8916 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8917 return false;
8919 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8920 &state_, target);
8921 if (!texture_ref) {
8922 LOCAL_SET_GL_ERROR(
8923 GL_INVALID_OPERATION,
8924 function_name, "unknown texture for target");
8925 return false;
8927 Texture* texture = texture_ref->texture();
8928 GLenum current_type = 0;
8929 GLenum internal_format = 0;
8930 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
8931 LOCAL_SET_GL_ERROR(
8932 GL_INVALID_OPERATION, function_name, "level does not exist.");
8933 return false;
8935 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8936 function_name, format, type, internal_format, level)) {
8937 return false;
8939 if (type != current_type) {
8940 LOCAL_SET_GL_ERROR(
8941 GL_INVALID_OPERATION,
8942 function_name, "type does not match type of texture.");
8943 return false;
8945 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8946 LOCAL_SET_GL_ERROR(
8947 GL_INVALID_OPERATION,
8948 function_name, "async upload pending for texture");
8949 return false;
8951 if (!texture->ValidForTexture(
8952 target, level, xoffset, yoffset, width, height, type)) {
8953 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8954 return false;
8956 if ((GLES2Util::GetChannelsForFormat(format) &
8957 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8958 LOCAL_SET_GL_ERROR(
8959 GL_INVALID_OPERATION,
8960 function_name, "can not supply data for depth or stencil textures");
8961 return false;
8963 if (data == NULL) {
8964 (*error) = error::kOutOfBounds;
8965 return false;
8967 return true;
8970 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8971 GLenum target,
8972 GLint level,
8973 GLint xoffset,
8974 GLint yoffset,
8975 GLsizei width,
8976 GLsizei height,
8977 GLenum format,
8978 GLenum type,
8979 const void * data) {
8980 error::Error error = error::kNoError;
8981 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8982 xoffset, yoffset, width, height, format, type, data)) {
8983 return error;
8985 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8986 &state_, target);
8987 Texture* texture = texture_ref->texture();
8988 GLsizei tex_width = 0;
8989 GLsizei tex_height = 0;
8990 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8991 DCHECK(ok);
8992 if (xoffset != 0 || yoffset != 0 ||
8993 width != tex_width || height != tex_height) {
8994 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8995 target, level)) {
8996 LOCAL_SET_GL_ERROR(
8997 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8998 return error::kNoError;
9000 ScopedTextureUploadTimer timer(&texture_state_);
9001 glTexSubImage2D(
9002 target, level, xoffset, yoffset, width, height, format, type, data);
9003 return error::kNoError;
9006 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
9007 !texture->IsImmutable()) {
9008 ScopedTextureUploadTimer timer(&texture_state_);
9009 GLenum internal_format;
9010 GLenum tex_type;
9011 texture->GetLevelType(target, level, &tex_type, &internal_format);
9012 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9013 // to look it up.
9014 glTexImage2D(
9015 target, level, internal_format, width, height, 0, format, type, data);
9016 } else {
9017 ScopedTextureUploadTimer timer(&texture_state_);
9018 glTexSubImage2D(
9019 target, level, xoffset, yoffset, width, height, format, type, data);
9021 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9023 // This may be a slow command. Exit command processing to allow for
9024 // context preemption and GPU watchdog checks.
9025 ExitCommandProcessingEarly();
9026 return error::kNoError;
9029 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
9030 const void* cmd_data) {
9031 const gles2::cmds::TexSubImage2D& c =
9032 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
9033 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9034 "width", c.width, "height", c.height);
9035 GLboolean internal = static_cast<GLboolean>(c.internal);
9036 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
9037 return error::kNoError;
9039 GLenum target = static_cast<GLenum>(c.target);
9040 GLint level = static_cast<GLint>(c.level);
9041 GLint xoffset = static_cast<GLint>(c.xoffset);
9042 GLint yoffset = static_cast<GLint>(c.yoffset);
9043 GLsizei width = static_cast<GLsizei>(c.width);
9044 GLsizei height = static_cast<GLsizei>(c.height);
9045 GLenum format = static_cast<GLenum>(c.format);
9046 GLenum type = static_cast<GLenum>(c.type);
9047 uint32 data_size;
9048 if (!GLES2Util::ComputeImageDataSizes(
9049 width, height, format, type, state_.unpack_alignment, &data_size,
9050 NULL, NULL)) {
9051 return error::kOutOfBounds;
9053 const void* pixels = GetSharedMemoryAs<const void*>(
9054 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9055 return DoTexSubImage2D(
9056 target, level, xoffset, yoffset, width, height, format, type, pixels);
9059 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9060 uint32 immediate_data_size,
9061 const void* cmd_data) {
9062 const gles2::cmds::GetVertexAttribPointerv& c =
9063 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
9064 GLuint index = static_cast<GLuint>(c.index);
9065 GLenum pname = static_cast<GLenum>(c.pname);
9066 typedef cmds::GetVertexAttribPointerv::Result Result;
9067 Result* result = GetSharedMemoryAs<Result*>(
9068 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
9069 if (!result) {
9070 return error::kOutOfBounds;
9072 // Check that the client initialized the result.
9073 if (result->size != 0) {
9074 return error::kInvalidArguments;
9076 if (!validators_->vertex_pointer.IsValid(pname)) {
9077 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9078 "glGetVertexAttribPointerv", pname, "pname");
9079 return error::kNoError;
9081 if (index >= group_->max_vertex_attribs()) {
9082 LOCAL_SET_GL_ERROR(
9083 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
9084 return error::kNoError;
9086 result->SetNumResults(1);
9087 *result->GetData() =
9088 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
9089 return error::kNoError;
9092 bool GLES2DecoderImpl::GetUniformSetup(
9093 GLuint program_id, GLint fake_location,
9094 uint32 shm_id, uint32 shm_offset,
9095 error::Error* error, GLint* real_location,
9096 GLuint* service_id, void** result_pointer, GLenum* result_type) {
9097 DCHECK(error);
9098 DCHECK(service_id);
9099 DCHECK(result_pointer);
9100 DCHECK(result_type);
9101 DCHECK(real_location);
9102 *error = error::kNoError;
9103 // Make sure we have enough room for the result on failure.
9104 SizedResult<GLint>* result;
9105 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9106 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
9107 if (!result) {
9108 *error = error::kOutOfBounds;
9109 return false;
9111 *result_pointer = result;
9112 // Set the result size to 0 so the client does not have to check for success.
9113 result->SetNumResults(0);
9114 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
9115 if (!program) {
9116 return false;
9118 if (!program->IsValid()) {
9119 // Program was not linked successfully. (ie, glLinkProgram)
9120 LOCAL_SET_GL_ERROR(
9121 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
9122 return false;
9124 *service_id = program->service_id();
9125 GLint array_index = -1;
9126 const Program::UniformInfo* uniform_info =
9127 program->GetUniformInfoByFakeLocation(
9128 fake_location, real_location, &array_index);
9129 if (!uniform_info) {
9130 // No such location.
9131 LOCAL_SET_GL_ERROR(
9132 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
9133 return false;
9135 GLenum type = uniform_info->type;
9136 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
9137 if (size == 0) {
9138 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
9139 return false;
9141 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9142 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
9143 if (!result) {
9144 *error = error::kOutOfBounds;
9145 return false;
9147 result->size = size;
9148 *result_type = type;
9149 return true;
9152 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
9153 const void* cmd_data) {
9154 const gles2::cmds::GetUniformiv& c =
9155 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
9156 GLuint program = c.program;
9157 GLint fake_location = c.location;
9158 GLuint service_id;
9159 GLenum result_type;
9160 GLint real_location = -1;
9161 Error error;
9162 void* result;
9163 if (GetUniformSetup(
9164 program, fake_location, c.params_shm_id, c.params_shm_offset,
9165 &error, &real_location, &service_id, &result, &result_type)) {
9166 glGetUniformiv(
9167 service_id, real_location,
9168 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
9170 return error;
9173 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
9174 const void* cmd_data) {
9175 const gles2::cmds::GetUniformfv& c =
9176 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
9177 GLuint program = c.program;
9178 GLint fake_location = c.location;
9179 GLuint service_id;
9180 GLint real_location = -1;
9181 Error error;
9182 typedef cmds::GetUniformfv::Result Result;
9183 Result* result;
9184 GLenum result_type;
9185 if (GetUniformSetup(
9186 program, fake_location, c.params_shm_id, c.params_shm_offset,
9187 &error, &real_location, &service_id,
9188 reinterpret_cast<void**>(&result), &result_type)) {
9189 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
9190 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
9191 GLsizei num_values = result->GetNumResults();
9192 scoped_ptr<GLint[]> temp(new GLint[num_values]);
9193 glGetUniformiv(service_id, real_location, temp.get());
9194 GLfloat* dst = result->GetData();
9195 for (GLsizei ii = 0; ii < num_values; ++ii) {
9196 dst[ii] = (temp[ii] != 0);
9198 } else {
9199 glGetUniformfv(service_id, real_location, result->GetData());
9202 return error;
9205 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9206 uint32 immediate_data_size,
9207 const void* cmd_data) {
9208 const gles2::cmds::GetShaderPrecisionFormat& c =
9209 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
9210 GLenum shader_type = static_cast<GLenum>(c.shadertype);
9211 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
9212 typedef cmds::GetShaderPrecisionFormat::Result Result;
9213 Result* result = GetSharedMemoryAs<Result*>(
9214 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9215 if (!result) {
9216 return error::kOutOfBounds;
9218 // Check that the client initialized the result.
9219 if (result->success != 0) {
9220 return error::kInvalidArguments;
9222 if (!validators_->shader_type.IsValid(shader_type)) {
9223 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9224 "glGetShaderPrecisionFormat", shader_type, "shader_type");
9225 return error::kNoError;
9227 if (!validators_->shader_precision.IsValid(precision_type)) {
9228 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9229 "glGetShaderPrecisionFormat", precision_type, "precision_type");
9230 return error::kNoError;
9233 result->success = 1; // true
9235 GLint range[2] = { 0, 0 };
9236 GLint precision = 0;
9237 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
9239 result->min_range = range[0];
9240 result->max_range = range[1];
9241 result->precision = precision;
9243 return error::kNoError;
9246 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
9247 uint32 immediate_data_size,
9248 const void* cmd_data) {
9249 const gles2::cmds::GetAttachedShaders& c =
9250 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
9251 uint32 result_size = c.result_size;
9252 GLuint program_id = static_cast<GLuint>(c.program);
9253 Program* program = GetProgramInfoNotShader(
9254 program_id, "glGetAttachedShaders");
9255 if (!program) {
9256 return error::kNoError;
9258 typedef cmds::GetAttachedShaders::Result Result;
9259 uint32 max_count = Result::ComputeMaxResults(result_size);
9260 Result* result = GetSharedMemoryAs<Result*>(
9261 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
9262 if (!result) {
9263 return error::kOutOfBounds;
9265 // Check that the client initialized the result.
9266 if (result->size != 0) {
9267 return error::kInvalidArguments;
9269 GLsizei count = 0;
9270 glGetAttachedShaders(
9271 program->service_id(), max_count, &count, result->GetData());
9272 for (GLsizei ii = 0; ii < count; ++ii) {
9273 if (!shader_manager()->GetClientId(result->GetData()[ii],
9274 &result->GetData()[ii])) {
9275 NOTREACHED();
9276 return error::kGenericError;
9279 result->SetNumResults(count);
9280 return error::kNoError;
9283 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
9284 uint32 immediate_data_size,
9285 const void* cmd_data) {
9286 const gles2::cmds::GetActiveUniform& c =
9287 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
9288 GLuint program_id = c.program;
9289 GLuint index = c.index;
9290 uint32 name_bucket_id = c.name_bucket_id;
9291 typedef cmds::GetActiveUniform::Result Result;
9292 Result* result = GetSharedMemoryAs<Result*>(
9293 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9294 if (!result) {
9295 return error::kOutOfBounds;
9297 // Check that the client initialized the result.
9298 if (result->success != 0) {
9299 return error::kInvalidArguments;
9301 Program* program = GetProgramInfoNotShader(
9302 program_id, "glGetActiveUniform");
9303 if (!program) {
9304 return error::kNoError;
9306 const Program::UniformInfo* uniform_info =
9307 program->GetUniformInfo(index);
9308 if (!uniform_info) {
9309 LOCAL_SET_GL_ERROR(
9310 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
9311 return error::kNoError;
9313 result->success = 1; // true.
9314 result->size = uniform_info->size;
9315 result->type = uniform_info->type;
9316 Bucket* bucket = CreateBucket(name_bucket_id);
9317 bucket->SetFromString(uniform_info->name.c_str());
9318 return error::kNoError;
9321 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
9322 const void* cmd_data) {
9323 const gles2::cmds::GetActiveAttrib& c =
9324 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
9325 GLuint program_id = c.program;
9326 GLuint index = c.index;
9327 uint32 name_bucket_id = c.name_bucket_id;
9328 typedef cmds::GetActiveAttrib::Result Result;
9329 Result* result = GetSharedMemoryAs<Result*>(
9330 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9331 if (!result) {
9332 return error::kOutOfBounds;
9334 // Check that the client initialized the result.
9335 if (result->success != 0) {
9336 return error::kInvalidArguments;
9338 Program* program = GetProgramInfoNotShader(
9339 program_id, "glGetActiveAttrib");
9340 if (!program) {
9341 return error::kNoError;
9343 const Program::VertexAttrib* attrib_info =
9344 program->GetAttribInfo(index);
9345 if (!attrib_info) {
9346 LOCAL_SET_GL_ERROR(
9347 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9348 return error::kNoError;
9350 result->success = 1; // true.
9351 result->size = attrib_info->size;
9352 result->type = attrib_info->type;
9353 Bucket* bucket = CreateBucket(name_bucket_id);
9354 bucket->SetFromString(attrib_info->name.c_str());
9355 return error::kNoError;
9358 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
9359 const void* cmd_data) {
9360 #if 1 // No binary shader support.
9361 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9362 return error::kNoError;
9363 #else
9364 GLsizei n = static_cast<GLsizei>(c.n);
9365 if (n < 0) {
9366 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9367 return error::kNoError;
9369 GLsizei length = static_cast<GLsizei>(c.length);
9370 if (length < 0) {
9371 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9372 return error::kNoError;
9374 uint32 data_size;
9375 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9376 return error::kOutOfBounds;
9378 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9379 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9380 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9381 const void* binary = GetSharedMemoryAs<const void*>(
9382 c.binary_shm_id, c.binary_shm_offset, length);
9383 if (shaders == NULL || binary == NULL) {
9384 return error::kOutOfBounds;
9386 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9387 for (GLsizei ii = 0; ii < n; ++ii) {
9388 Shader* shader = GetShader(shaders[ii]);
9389 if (!shader) {
9390 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9391 return error::kNoError;
9393 service_ids[ii] = shader->service_id();
9395 // TODO(gman): call glShaderBinary
9396 return error::kNoError;
9397 #endif
9400 void GLES2DecoderImpl::DoSwapBuffers() {
9401 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9403 int this_frame_number = frame_number_++;
9404 // TRACE_EVENT for gpu tests:
9405 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9406 TRACE_EVENT_SCOPE_THREAD,
9407 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9408 "width", (is_offscreen ? offscreen_size_.width() :
9409 surface_->GetSize().width()));
9410 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9411 "offscreen", is_offscreen,
9412 "frame", this_frame_number);
9414 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9417 bool is_tracing;
9418 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9419 &is_tracing);
9420 if (is_tracing) {
9421 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9422 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9423 is_offscreen ? offscreen_size_ : surface_->GetSize());
9426 // If offscreen then don't actually SwapBuffers to the display. Just copy
9427 // the rendered frame to another frame buffer.
9428 if (is_offscreen) {
9429 TRACE_EVENT2("gpu", "Offscreen",
9430 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9431 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9432 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9433 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9434 // fix this.
9435 if (workarounds().needs_offscreen_buffer_workaround) {
9436 offscreen_saved_frame_buffer_->Create();
9437 glFinish();
9440 // Allocate the offscreen saved color texture.
9441 DCHECK(offscreen_saved_color_format_);
9442 offscreen_saved_color_texture_->AllocateStorage(
9443 offscreen_size_, offscreen_saved_color_format_, false);
9445 offscreen_saved_frame_buffer_->AttachRenderTexture(
9446 offscreen_saved_color_texture_.get());
9447 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9448 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9449 GL_FRAMEBUFFER_COMPLETE) {
9450 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9451 << "because offscreen saved FBO was incomplete.";
9452 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9453 return;
9456 // Clear the offscreen color texture.
9457 // TODO(piman): Is this still necessary?
9459 ScopedFrameBufferBinder binder(this,
9460 offscreen_saved_frame_buffer_->id());
9461 glClearColor(0, 0, 0, 0);
9462 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9463 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9464 glClear(GL_COLOR_BUFFER_BIT);
9465 RestoreClearState();
9469 UpdateParentTextureInfo();
9472 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9473 return;
9474 ScopedGLErrorSuppressor suppressor(
9475 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9477 if (IsOffscreenBufferMultisampled()) {
9478 // For multisampled buffers, resolve the frame buffer.
9479 ScopedResolvedFrameBufferBinder binder(this, true, false);
9480 } else {
9481 ScopedFrameBufferBinder binder(this,
9482 offscreen_target_frame_buffer_->id());
9484 if (offscreen_target_buffer_preserved_) {
9485 // Copy the target frame buffer to the saved offscreen texture.
9486 offscreen_saved_color_texture_->Copy(
9487 offscreen_saved_color_texture_->size(),
9488 offscreen_saved_color_format_);
9489 } else {
9490 // Flip the textures in the parent context via the texture manager.
9491 if (!!offscreen_saved_color_texture_info_.get())
9492 offscreen_saved_color_texture_info_->texture()->
9493 SetServiceId(offscreen_target_color_texture_->id());
9495 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9496 offscreen_target_frame_buffer_->AttachRenderTexture(
9497 offscreen_target_color_texture_.get());
9500 // Ensure the side effects of the copy are visible to the parent
9501 // context. There is no need to do this for ANGLE because it uses a
9502 // single D3D device for all contexts.
9503 if (!feature_info_->feature_flags().is_angle)
9504 glFlush();
9506 } else {
9507 if (!surface_->SwapBuffers()) {
9508 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9509 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9513 // This may be a slow command. Exit command processing to allow for
9514 // context preemption and GPU watchdog checks.
9515 ExitCommandProcessingEarly();
9518 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9519 uint32 immediate_data_size,
9520 const void* cmd_data) {
9521 const gles2::cmds::EnableFeatureCHROMIUM& c =
9522 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
9523 Bucket* bucket = GetBucket(c.bucket_id);
9524 if (!bucket || bucket->size() == 0) {
9525 return error::kInvalidArguments;
9527 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9528 Result* result = GetSharedMemoryAs<Result*>(
9529 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9530 if (!result) {
9531 return error::kOutOfBounds;
9533 // Check that the client initialized the result.
9534 if (*result != 0) {
9535 return error::kInvalidArguments;
9537 std::string feature_str;
9538 if (!bucket->GetAsString(&feature_str)) {
9539 return error::kInvalidArguments;
9542 // TODO(gman): make this some kind of table to function pointer thingy.
9543 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9544 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9545 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9546 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9547 // TODO(gman): decide how to remove the need for this const_cast.
9548 // I could make validators_ non const but that seems bad as this is the only
9549 // place it is needed. I could make some special friend class of validators
9550 // just to allow this to set them. That seems silly. I could refactor this
9551 // code to use the extension mechanism or the initialization attributes to
9552 // turn this feature on. Given that the only real point of this is to make
9553 // the conformance tests pass and given that there is lots of real work that
9554 // needs to be done it seems like refactoring for one to one of those
9555 // methods is a very low priority.
9556 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9557 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9558 force_webgl_glsl_validation_ = true;
9559 InitializeShaderTranslator();
9560 } else {
9561 return error::kNoError;
9564 *result = 1; // true.
9565 return error::kNoError;
9568 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9569 uint32 immediate_data_size,
9570 const void* cmd_data) {
9571 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
9572 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
9573 cmd_data);
9574 Bucket* bucket = CreateBucket(c.bucket_id);
9575 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9576 info->Initialize(disallowed_features_);
9577 bucket->SetFromString(info->extensions().c_str());
9578 return error::kNoError;
9581 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9582 uint32 immediate_data_size,
9583 const void* cmd_data) {
9584 const gles2::cmds::RequestExtensionCHROMIUM& c =
9585 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
9586 Bucket* bucket = GetBucket(c.bucket_id);
9587 if (!bucket || bucket->size() == 0) {
9588 return error::kInvalidArguments;
9590 std::string feature_str;
9591 if (!bucket->GetAsString(&feature_str)) {
9592 return error::kInvalidArguments;
9595 bool desire_webgl_glsl_validation =
9596 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9597 bool desire_standard_derivatives = false;
9598 bool desire_frag_depth = false;
9599 bool desire_draw_buffers = false;
9600 bool desire_shader_texture_lod = false;
9601 if (force_webgl_glsl_validation_) {
9602 desire_standard_derivatives =
9603 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9604 desire_frag_depth =
9605 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9606 desire_draw_buffers =
9607 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9608 desire_shader_texture_lod =
9609 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9612 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9613 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9614 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9615 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9616 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9617 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9618 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9619 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9620 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
9621 InitializeShaderTranslator();
9624 UpdateCapabilities();
9626 return error::kNoError;
9629 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9630 uint32 immediate_data_size,
9631 const void* cmd_data) {
9632 const gles2::cmds::GetMultipleIntegervCHROMIUM& c =
9633 *static_cast<const gles2::cmds::GetMultipleIntegervCHROMIUM*>(cmd_data);
9634 GLuint count = c.count;
9635 uint32 pnames_size;
9636 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9637 return error::kOutOfBounds;
9639 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9640 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9641 if (pnames == NULL) {
9642 return error::kOutOfBounds;
9645 // We have to copy them since we use them twice so the client
9646 // can't change them between the time we validate them and the time we use
9647 // them.
9648 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9649 memcpy(enums.get(), pnames, pnames_size);
9651 // Count up the space needed for the result.
9652 uint32 num_results = 0;
9653 for (GLuint ii = 0; ii < count; ++ii) {
9654 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9655 if (num == 0) {
9656 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9657 "glGetMultipleCHROMIUM", enums[ii], "pname");
9658 return error::kNoError;
9660 // Num will never be more than 4.
9661 DCHECK_LE(num, 4u);
9662 if (!SafeAddUint32(num_results, num, &num_results)) {
9663 return error::kOutOfBounds;
9667 uint32 result_size = 0;
9668 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9669 return error::kOutOfBounds;
9672 if (result_size != static_cast<uint32>(c.size)) {
9673 LOCAL_SET_GL_ERROR(
9674 GL_INVALID_VALUE,
9675 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9676 return error::kNoError;
9679 GLint* results = GetSharedMemoryAs<GLint*>(
9680 c.results_shm_id, c.results_shm_offset, result_size);
9681 if (results == NULL) {
9682 return error::kOutOfBounds;
9685 // Check the results have been cleared in case the context was lost.
9686 for (uint32 ii = 0; ii < num_results; ++ii) {
9687 if (results[ii]) {
9688 return error::kInvalidArguments;
9692 // Get each result.
9693 GLint* start = results;
9694 for (GLuint ii = 0; ii < count; ++ii) {
9695 GLsizei num_written = 0;
9696 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9697 !GetHelper(enums[ii], results, &num_written)) {
9698 DoGetIntegerv(enums[ii], results);
9700 results += num_written;
9703 // Just to verify. Should this be a DCHECK?
9704 if (static_cast<uint32>(results - start) != num_results) {
9705 return error::kOutOfBounds;
9708 return error::kNoError;
9711 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9712 uint32 immediate_data_size,
9713 const void* cmd_data) {
9714 const gles2::cmds::GetProgramInfoCHROMIUM& c =
9715 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
9716 GLuint program_id = static_cast<GLuint>(c.program);
9717 uint32 bucket_id = c.bucket_id;
9718 Bucket* bucket = CreateBucket(bucket_id);
9719 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9720 Program* program = NULL;
9721 program = GetProgram(program_id);
9722 if (!program || !program->IsValid()) {
9723 return error::kNoError;
9725 program->GetProgramInfo(program_manager(), bucket);
9726 return error::kNoError;
9729 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9730 switch (reset_status_) {
9731 case GL_NO_ERROR:
9732 // TODO(kbr): improve the precision of the error code in this case.
9733 // Consider delegating to context for error code if MakeCurrent fails.
9734 return error::kUnknown;
9735 case GL_GUILTY_CONTEXT_RESET_ARB:
9736 return error::kGuilty;
9737 case GL_INNOCENT_CONTEXT_RESET_ARB:
9738 return error::kInnocent;
9739 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9740 return error::kUnknown;
9743 NOTREACHED();
9744 return error::kUnknown;
9747 bool GLES2DecoderImpl::WasContextLost() {
9748 if (reset_status_ != GL_NO_ERROR) {
9749 return true;
9751 if (context_->WasAllocatedUsingRobustnessExtension()) {
9752 GLenum status = GL_NO_ERROR;
9753 if (has_robustness_extension_)
9754 status = glGetGraphicsResetStatusARB();
9755 if (status != GL_NO_ERROR) {
9756 // The graphics card was reset. Signal a lost context to the application.
9757 reset_status_ = status;
9758 reset_by_robustness_extension_ = true;
9759 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9760 << " context lost via ARB/EXT_robustness. Reset status = "
9761 << GLES2Util::GetStringEnum(status);
9762 return true;
9765 return false;
9768 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9769 return WasContextLost() && reset_by_robustness_extension_;
9772 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9773 // Only loses the context once.
9774 if (reset_status_ != GL_NO_ERROR) {
9775 return;
9778 // Marks this context as lost.
9779 reset_status_ = reset_status;
9780 current_decoder_error_ = error::kLostContext;
9783 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9784 uint32 immediate_data_size,
9785 const void* cmd_data) {
9786 return error::kUnknownCommand;
9789 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9790 uint32 immediate_data_size,
9791 const void* cmd_data) {
9792 const gles2::cmds::WaitSyncPointCHROMIUM& c =
9793 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
9794 group_->mailbox_manager()->PullTextureUpdates();
9795 if (wait_sync_point_callback_.is_null())
9796 return error::kNoError;
9798 return wait_sync_point_callback_.Run(c.sync_point) ?
9799 error::kNoError : error::kDeferCommandUntilLater;
9802 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9803 uint32 immediate_data_size,
9804 const void* cmd_data) {
9805 if (surface_->DeferDraws())
9806 return error::kDeferCommandUntilLater;
9807 if (!surface_->SetBackbufferAllocation(false))
9808 return error::kLostContext;
9809 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9810 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9811 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9812 return error::kNoError;
9815 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9816 GLsizei n, const GLuint* client_ids) {
9817 for (GLsizei ii = 0; ii < n; ++ii) {
9818 if (query_manager_->GetQuery(client_ids[ii])) {
9819 return false;
9822 query_manager_->GenQueries(n, client_ids);
9823 return true;
9826 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9827 GLsizei n, const GLuint* client_ids) {
9828 for (GLsizei ii = 0; ii < n; ++ii) {
9829 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9830 if (query && !query->IsDeleted()) {
9831 ContextState::QueryMap::iterator it =
9832 state_.current_queries.find(query->target());
9833 if (it != state_.current_queries.end())
9834 state_.current_queries.erase(it);
9836 query->Destroy(true);
9838 query_manager_->RemoveQuery(client_ids[ii]);
9842 bool GLES2DecoderImpl::ProcessPendingQueries() {
9843 if (query_manager_.get() == NULL) {
9844 return false;
9846 if (!query_manager_->ProcessPendingQueries()) {
9847 current_decoder_error_ = error::kOutOfBounds;
9849 return query_manager_->HavePendingQueries();
9852 // Note that if there are no pending readpixels right now,
9853 // this function will call the callback immediately.
9854 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9855 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9856 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9857 } else {
9858 callback.Run();
9862 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9863 while (!pending_readpixel_fences_.empty() &&
9864 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9865 std::vector<base::Closure> callbacks =
9866 pending_readpixel_fences_.front()->callbacks;
9867 pending_readpixel_fences_.pop();
9868 for (size_t i = 0; i < callbacks.size(); i++) {
9869 callbacks[i].Run();
9874 bool GLES2DecoderImpl::HasMoreIdleWork() {
9875 return !pending_readpixel_fences_.empty() ||
9876 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9879 void GLES2DecoderImpl::PerformIdleWork() {
9880 ProcessPendingReadPixels();
9881 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9882 return;
9883 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9884 ProcessFinishedAsyncTransfers();
9887 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
9888 const void* cmd_data) {
9889 const gles2::cmds::BeginQueryEXT& c =
9890 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
9891 GLenum target = static_cast<GLenum>(c.target);
9892 GLuint client_id = static_cast<GLuint>(c.id);
9893 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9894 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9896 switch (target) {
9897 case GL_COMMANDS_ISSUED_CHROMIUM:
9898 case GL_LATENCY_QUERY_CHROMIUM:
9899 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9900 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9901 case GL_GET_ERROR_QUERY_CHROMIUM:
9902 break;
9903 case GL_COMMANDS_COMPLETED_CHROMIUM:
9904 if (!features().chromium_sync_query) {
9905 LOCAL_SET_GL_ERROR(
9906 GL_INVALID_OPERATION, "glBeginQueryEXT",
9907 "not enabled for commands completed queries");
9908 return error::kNoError;
9910 break;
9911 default:
9912 if (!features().occlusion_query_boolean) {
9913 LOCAL_SET_GL_ERROR(
9914 GL_INVALID_OPERATION, "glBeginQueryEXT",
9915 "not enabled for occlusion queries");
9916 return error::kNoError;
9918 break;
9921 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9922 LOCAL_SET_GL_ERROR(
9923 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9924 return error::kNoError;
9927 if (client_id == 0) {
9928 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9929 return error::kNoError;
9932 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9933 if (!query) {
9934 if (!query_manager_->IsValidQuery(client_id)) {
9935 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9936 "glBeginQueryEXT",
9937 "id not made by glGenQueriesEXT");
9938 return error::kNoError;
9940 query = query_manager_->CreateQuery(
9941 target, client_id, sync_shm_id, sync_shm_offset);
9944 if (query->target() != target) {
9945 LOCAL_SET_GL_ERROR(
9946 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9947 return error::kNoError;
9948 } else if (query->shm_id() != sync_shm_id ||
9949 query->shm_offset() != sync_shm_offset) {
9950 DLOG(ERROR) << "Shared memory used by query not the same as before";
9951 return error::kInvalidArguments;
9954 if (!query_manager_->BeginQuery(query)) {
9955 return error::kOutOfBounds;
9958 state_.current_queries[target] = query;
9959 return error::kNoError;
9962 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
9963 const void* cmd_data) {
9964 const gles2::cmds::EndQueryEXT& c =
9965 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
9966 GLenum target = static_cast<GLenum>(c.target);
9967 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9968 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9970 if (it == state_.current_queries.end()) {
9971 LOCAL_SET_GL_ERROR(
9972 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9973 return error::kNoError;
9976 QueryManager::Query* query = it->second.get();
9977 if (!query_manager_->EndQuery(query, submit_count)) {
9978 return error::kOutOfBounds;
9981 query_manager_->ProcessPendingTransferQueries();
9983 state_.current_queries.erase(it);
9984 return error::kNoError;
9987 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9988 GLsizei n, const GLuint* client_ids) {
9989 for (GLsizei ii = 0; ii < n; ++ii) {
9990 if (GetVertexAttribManager(client_ids[ii])) {
9991 return false;
9995 if (!features().native_vertex_array_object) {
9996 // Emulated VAO
9997 for (GLsizei ii = 0; ii < n; ++ii) {
9998 CreateVertexAttribManager(client_ids[ii], 0, true);
10000 } else {
10001 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10003 glGenVertexArraysOES(n, service_ids.get());
10004 for (GLsizei ii = 0; ii < n; ++ii) {
10005 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
10009 return true;
10012 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10013 GLsizei n, const GLuint* client_ids) {
10014 for (GLsizei ii = 0; ii < n; ++ii) {
10015 VertexAttribManager* vao =
10016 GetVertexAttribManager(client_ids[ii]);
10017 if (vao && !vao->IsDeleted()) {
10018 if (state_.vertex_attrib_manager.get() == vao) {
10019 DoBindVertexArrayOES(0);
10021 RemoveVertexAttribManager(client_ids[ii]);
10026 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
10027 VertexAttribManager* vao = NULL;
10028 if (client_id != 0) {
10029 vao = GetVertexAttribManager(client_id);
10030 if (!vao) {
10031 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10032 // only allows names that have been previously generated. As such, we do
10033 // not generate new names here.
10034 LOCAL_SET_GL_ERROR(
10035 GL_INVALID_OPERATION,
10036 "glBindVertexArrayOES", "bad vertex array id.");
10037 current_decoder_error_ = error::kNoError;
10038 return;
10040 } else {
10041 vao = state_.default_vertex_attrib_manager.get();
10044 // Only set the VAO state if it's changed
10045 if (state_.vertex_attrib_manager.get() != vao) {
10046 state_.vertex_attrib_manager = vao;
10047 if (!features().native_vertex_array_object) {
10048 EmulateVertexArrayState();
10049 } else {
10050 GLuint service_id = vao->service_id();
10051 glBindVertexArrayOES(service_id);
10056 // Used when OES_vertex_array_object isn't natively supported
10057 void GLES2DecoderImpl::EmulateVertexArrayState() {
10058 // Setup the Vertex attribute state
10059 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
10060 RestoreStateForAttrib(vv, true);
10063 // Setup the element buffer
10064 Buffer* element_array_buffer =
10065 state_.vertex_attrib_manager->element_array_buffer();
10066 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
10067 element_array_buffer ? element_array_buffer->service_id() : 0);
10070 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
10071 const VertexAttribManager* vao =
10072 GetVertexAttribManager(client_id);
10073 return vao && vao->IsValid() && !vao->IsDeleted();
10076 #if defined(OS_MACOSX)
10077 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
10078 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
10079 texture_id);
10080 if (it != texture_to_io_surface_map_.end()) {
10081 // Found a previous IOSurface bound to this texture; release it.
10082 IOSurfaceRef surface = it->second;
10083 CFRelease(surface);
10084 texture_to_io_surface_map_.erase(it);
10087 #endif
10089 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10090 GLenum target, GLsizei width, GLsizei height,
10091 GLuint io_surface_id, GLuint plane) {
10092 #if defined(OS_MACOSX)
10093 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
10094 LOCAL_SET_GL_ERROR(
10095 GL_INVALID_OPERATION,
10096 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10097 return;
10100 if (target != GL_TEXTURE_RECTANGLE_ARB) {
10101 // This might be supported in the future, and if we could require
10102 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10103 // could delete a lot of code. For now, perform strict validation so we
10104 // know what's going on.
10105 LOCAL_SET_GL_ERROR(
10106 GL_INVALID_OPERATION,
10107 "glTexImageIOSurface2DCHROMIUM",
10108 "requires TEXTURE_RECTANGLE_ARB target");
10109 return;
10112 // Default target might be conceptually valid, but disallow it to avoid
10113 // accidents.
10114 TextureRef* texture_ref =
10115 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10116 if (!texture_ref) {
10117 LOCAL_SET_GL_ERROR(
10118 GL_INVALID_OPERATION,
10119 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10120 return;
10123 // Look up the new IOSurface. Note that because of asynchrony
10124 // between processes this might fail; during live resizing the
10125 // plugin process might allocate and release an IOSurface before
10126 // this process gets a chance to look it up. Hold on to any old
10127 // IOSurface in this case.
10128 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
10129 if (!surface) {
10130 LOCAL_SET_GL_ERROR(
10131 GL_INVALID_OPERATION,
10132 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
10133 return;
10136 // Release any IOSurface previously bound to this texture.
10137 ReleaseIOSurfaceForTexture(texture_ref->service_id());
10139 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
10140 texture_to_io_surface_map_.insert(
10141 std::make_pair(texture_ref->service_id(), surface));
10143 CGLContextObj context =
10144 static_cast<CGLContextObj>(context_->GetHandle());
10146 CGLError err = CGLTexImageIOSurface2D(
10147 context,
10148 target,
10149 GL_RGBA,
10150 width,
10151 height,
10152 GL_BGRA,
10153 GL_UNSIGNED_INT_8_8_8_8_REV,
10154 surface,
10155 plane);
10157 if (err != kCGLNoError) {
10158 LOCAL_SET_GL_ERROR(
10159 GL_INVALID_OPERATION,
10160 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
10161 return;
10164 texture_manager()->SetLevelInfo(
10165 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
10166 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
10168 #else
10169 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10170 "glTexImageIOSurface2DCHROMIUM", "not supported.");
10171 #endif
10174 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
10175 switch (internalformat) {
10176 case GL_RGB565:
10177 return GL_RGB;
10178 case GL_RGBA4:
10179 return GL_RGBA;
10180 case GL_RGB5_A1:
10181 return GL_RGBA;
10182 case GL_RGB8_OES:
10183 return GL_RGB;
10184 case GL_RGBA8_OES:
10185 return GL_RGBA;
10186 case GL_LUMINANCE8_ALPHA8_EXT:
10187 return GL_LUMINANCE_ALPHA;
10188 case GL_LUMINANCE8_EXT:
10189 return GL_LUMINANCE;
10190 case GL_ALPHA8_EXT:
10191 return GL_ALPHA;
10192 case GL_RGBA32F_EXT:
10193 return GL_RGBA;
10194 case GL_RGB32F_EXT:
10195 return GL_RGB;
10196 case GL_ALPHA32F_EXT:
10197 return GL_ALPHA;
10198 case GL_LUMINANCE32F_EXT:
10199 return GL_LUMINANCE;
10200 case GL_LUMINANCE_ALPHA32F_EXT:
10201 return GL_LUMINANCE_ALPHA;
10202 case GL_RGBA16F_EXT:
10203 return GL_RGBA;
10204 case GL_RGB16F_EXT:
10205 return GL_RGB;
10206 case GL_ALPHA16F_EXT:
10207 return GL_ALPHA;
10208 case GL_LUMINANCE16F_EXT:
10209 return GL_LUMINANCE;
10210 case GL_LUMINANCE_ALPHA16F_EXT:
10211 return GL_LUMINANCE_ALPHA;
10212 case GL_BGRA8_EXT:
10213 return GL_BGRA_EXT;
10214 default:
10215 return GL_NONE;
10219 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
10220 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
10221 GLenum internal_format, GLenum dest_type) {
10222 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
10224 TextureRef* dest_texture_ref = GetTexture(dest_id);
10225 TextureRef* source_texture_ref = GetTexture(source_id);
10227 if (!source_texture_ref || !dest_texture_ref) {
10228 LOCAL_SET_GL_ERROR(
10229 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
10230 return;
10233 if (GL_TEXTURE_2D != target) {
10234 LOCAL_SET_GL_ERROR(
10235 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
10236 return;
10239 Texture* source_texture = source_texture_ref->texture();
10240 Texture* dest_texture = dest_texture_ref->texture();
10241 if (dest_texture->target() != GL_TEXTURE_2D ||
10242 (source_texture->target() != GL_TEXTURE_2D &&
10243 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
10244 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
10245 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10246 "glCopyTextureCHROMIUM",
10247 "invalid texture target binding");
10248 return;
10251 int source_width, source_height, dest_width, dest_height;
10253 gfx::GLImage* image =
10254 source_texture->GetLevelImage(source_texture->target(), 0);
10255 if (image) {
10256 gfx::Size size = image->GetSize();
10257 source_width = size.width();
10258 source_height = size.height();
10259 if (source_width <= 0 || source_height <= 0) {
10260 LOCAL_SET_GL_ERROR(
10261 GL_INVALID_VALUE,
10262 "glCopyTextureChromium", "invalid image size");
10263 return;
10265 } else {
10266 if (!source_texture->GetLevelSize(
10267 source_texture->target(), 0, &source_width, &source_height)) {
10268 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10269 "glCopyTextureChromium",
10270 "source texture has no level 0");
10271 return;
10274 // Check that this type of texture is allowed.
10275 if (!texture_manager()->ValidForTarget(
10276 source_texture->target(), level, source_width, source_height, 1)) {
10277 LOCAL_SET_GL_ERROR(
10278 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
10279 return;
10283 // Clear the source texture if necessary.
10284 if (!texture_manager()->ClearTextureLevel(
10285 this, source_texture_ref, source_texture->target(), 0)) {
10286 LOCAL_SET_GL_ERROR(
10287 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
10288 return;
10291 GLenum source_type = 0;
10292 GLenum source_internal_format = 0;
10293 source_texture->GetLevelType(
10294 source_texture->target(), 0, &source_type, &source_internal_format);
10296 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
10297 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
10298 // renderable on some platforms.
10299 bool valid_dest_format = internal_format == GL_RGB ||
10300 internal_format == GL_RGBA ||
10301 internal_format == GL_BGRA_EXT;
10302 bool valid_source_format = source_internal_format == GL_ALPHA ||
10303 source_internal_format == GL_RGB ||
10304 source_internal_format == GL_RGBA ||
10305 source_internal_format == GL_LUMINANCE ||
10306 source_internal_format == GL_LUMINANCE_ALPHA ||
10307 source_internal_format == GL_BGRA_EXT;
10308 if (!valid_source_format || !valid_dest_format) {
10309 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10310 "glCopyTextureCHROMIUM",
10311 "invalid internal format");
10312 return;
10315 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10316 // needed because it takes 10s of milliseconds to initialize.
10317 if (!copy_texture_CHROMIUM_.get()) {
10318 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10319 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
10320 copy_texture_CHROMIUM_->Initialize(this);
10321 RestoreCurrentFramebufferBindings();
10322 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
10323 return;
10326 GLenum dest_type_previous = dest_type;
10327 GLenum dest_internal_format = internal_format;
10328 bool dest_level_defined = dest_texture->GetLevelSize(
10329 GL_TEXTURE_2D, level, &dest_width, &dest_height);
10331 if (dest_level_defined) {
10332 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
10333 &dest_internal_format);
10336 // Resize the destination texture to the dimensions of the source texture.
10337 if (!dest_level_defined || dest_width != source_width ||
10338 dest_height != source_height ||
10339 dest_internal_format != internal_format ||
10340 dest_type_previous != dest_type) {
10341 // Ensure that the glTexImage2D succeeds.
10342 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10343 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10344 glTexImage2D(
10345 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
10346 0, internal_format, dest_type, NULL);
10347 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10348 if (error != GL_NO_ERROR) {
10349 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
10350 return;
10353 texture_manager()->SetLevelInfo(
10354 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
10355 source_height, 1, 0, internal_format, dest_type, true);
10356 } else {
10357 texture_manager()->SetLevelCleared(
10358 dest_texture_ref, GL_TEXTURE_2D, level, true);
10361 ScopedModifyPixels modify(dest_texture_ref);
10363 // Try using GLImage::CopyTexImage when possible.
10364 bool unpack_premultiply_alpha_change =
10365 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
10366 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change && !level) {
10367 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10368 if (image->CopyTexImage(GL_TEXTURE_2D))
10369 return;
10372 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
10374 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10375 // before presenting.
10376 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
10377 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10378 // instead of using default matrix crbug.com/226218.
10379 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
10380 0.0f, 1.0f, 0.0f, 0.0f,
10381 0.0f, 0.0f, 1.0f, 0.0f,
10382 0.0f, 0.0f, 0.0f, 1.0f};
10383 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
10384 this,
10385 source_texture->target(),
10386 source_texture->service_id(),
10387 dest_texture->service_id(),
10388 level,
10389 source_width,
10390 source_height,
10391 unpack_flip_y_,
10392 unpack_premultiply_alpha_,
10393 unpack_unpremultiply_alpha_,
10394 default_matrix);
10395 } else {
10396 copy_texture_CHROMIUM_->DoCopyTexture(this,
10397 source_texture->target(),
10398 source_texture->service_id(),
10399 source_internal_format,
10400 dest_texture->service_id(),
10401 level,
10402 internal_format,
10403 source_width,
10404 source_height,
10405 unpack_flip_y_,
10406 unpack_premultiply_alpha_,
10407 unpack_unpremultiply_alpha_);
10410 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10413 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10414 switch (internalformat) {
10415 case GL_RGB565:
10416 return GL_UNSIGNED_SHORT_5_6_5;
10417 case GL_RGBA4:
10418 return GL_UNSIGNED_SHORT_4_4_4_4;
10419 case GL_RGB5_A1:
10420 return GL_UNSIGNED_SHORT_5_5_5_1;
10421 case GL_RGB8_OES:
10422 return GL_UNSIGNED_BYTE;
10423 case GL_RGBA8_OES:
10424 return GL_UNSIGNED_BYTE;
10425 case GL_LUMINANCE8_ALPHA8_EXT:
10426 return GL_UNSIGNED_BYTE;
10427 case GL_LUMINANCE8_EXT:
10428 return GL_UNSIGNED_BYTE;
10429 case GL_ALPHA8_EXT:
10430 return GL_UNSIGNED_BYTE;
10431 case GL_RGBA32F_EXT:
10432 return GL_FLOAT;
10433 case GL_RGB32F_EXT:
10434 return GL_FLOAT;
10435 case GL_ALPHA32F_EXT:
10436 return GL_FLOAT;
10437 case GL_LUMINANCE32F_EXT:
10438 return GL_FLOAT;
10439 case GL_LUMINANCE_ALPHA32F_EXT:
10440 return GL_FLOAT;
10441 case GL_RGBA16F_EXT:
10442 return GL_HALF_FLOAT_OES;
10443 case GL_RGB16F_EXT:
10444 return GL_HALF_FLOAT_OES;
10445 case GL_ALPHA16F_EXT:
10446 return GL_HALF_FLOAT_OES;
10447 case GL_LUMINANCE16F_EXT:
10448 return GL_HALF_FLOAT_OES;
10449 case GL_LUMINANCE_ALPHA16F_EXT:
10450 return GL_HALF_FLOAT_OES;
10451 case GL_BGRA8_EXT:
10452 return GL_UNSIGNED_BYTE;
10453 default:
10454 return GL_NONE;
10458 void GLES2DecoderImpl::DoTexStorage2DEXT(
10459 GLenum target,
10460 GLint levels,
10461 GLenum internal_format,
10462 GLsizei width,
10463 GLsizei height) {
10464 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10465 "width", width, "height", height);
10466 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10467 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10468 LOCAL_SET_GL_ERROR(
10469 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10470 return;
10472 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10473 &state_, target);
10474 if (!texture_ref) {
10475 LOCAL_SET_GL_ERROR(
10476 GL_INVALID_OPERATION,
10477 "glTexStorage2DEXT", "unknown texture for target");
10478 return;
10480 Texture* texture = texture_ref->texture();
10481 if (texture->IsAttachedToFramebuffer()) {
10482 framebuffer_state_.clear_state_dirty = true;
10484 if (texture->IsImmutable()) {
10485 LOCAL_SET_GL_ERROR(
10486 GL_INVALID_OPERATION,
10487 "glTexStorage2DEXT", "texture is immutable");
10488 return;
10491 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10492 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10495 GLsizei level_width = width;
10496 GLsizei level_height = height;
10497 uint32 estimated_size = 0;
10498 for (int ii = 0; ii < levels; ++ii) {
10499 uint32 level_size = 0;
10500 if (!GLES2Util::ComputeImageDataSizes(
10501 level_width, level_height, format, type, state_.unpack_alignment,
10502 &estimated_size, NULL, NULL) ||
10503 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10504 LOCAL_SET_GL_ERROR(
10505 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10506 return;
10508 level_width = std::max(1, level_width >> 1);
10509 level_height = std::max(1, level_height >> 1);
10511 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10512 LOCAL_SET_GL_ERROR(
10513 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10514 return;
10518 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10519 glTexStorage2DEXT(target, levels, internal_format, width, height);
10520 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10521 if (error == GL_NO_ERROR) {
10522 GLsizei level_width = width;
10523 GLsizei level_height = height;
10524 for (int ii = 0; ii < levels; ++ii) {
10525 texture_manager()->SetLevelInfo(
10526 texture_ref, target, ii, format,
10527 level_width, level_height, 1, 0, format, type, false);
10528 level_width = std::max(1, level_width >> 1);
10529 level_height = std::max(1, level_height >> 1);
10531 texture->SetImmutable(true);
10535 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10536 uint32 immediate_data_size,
10537 const void* cmd_data) {
10538 return error::kUnknownCommand;
10541 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10542 const GLbyte* data) {
10543 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10544 "context", logger_.GetLogPrefix(),
10545 "mailbox[0]", static_cast<unsigned char>(data[0]));
10547 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10548 &state_, target);
10549 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
10552 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
10553 GLenum target, const GLbyte* data) {
10554 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10555 "context", logger_.GetLogPrefix(),
10556 "mailbox[0]", static_cast<unsigned char>(data[0]));
10558 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
10559 target, data);
10562 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
10563 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
10564 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10565 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
10566 "mailbox that was not generated by "
10567 "GenMailboxCHROMIUM.";
10569 if (!texture_ref) {
10570 LOCAL_SET_GL_ERROR(
10571 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
10572 return;
10575 Texture* produced = texture_manager()->Produce(texture_ref);
10576 if (!produced) {
10577 LOCAL_SET_GL_ERROR(
10578 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
10579 return;
10582 if (produced->target() != target) {
10583 LOCAL_SET_GL_ERROR(
10584 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
10585 return;
10588 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10591 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10592 const GLbyte* data) {
10593 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10594 "context", logger_.GetLogPrefix(),
10595 "mailbox[0]", static_cast<unsigned char>(data[0]));
10596 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10597 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10598 "mailbox that was not generated by "
10599 "GenMailboxCHROMIUM.";
10601 scoped_refptr<TextureRef> texture_ref =
10602 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10603 if (!texture_ref.get()) {
10604 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10605 "glConsumeTextureCHROMIUM",
10606 "unknown texture for target");
10607 return;
10609 GLuint client_id = texture_ref->client_id();
10610 if (!client_id) {
10611 LOCAL_SET_GL_ERROR(
10612 GL_INVALID_OPERATION,
10613 "glConsumeTextureCHROMIUM", "unknown texture for target");
10614 return;
10616 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10617 if (!texture) {
10618 LOCAL_SET_GL_ERROR(
10619 GL_INVALID_OPERATION,
10620 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10621 return;
10623 if (texture->target() != target) {
10624 LOCAL_SET_GL_ERROR(
10625 GL_INVALID_OPERATION,
10626 "glConsumeTextureCHROMIUM", "invalid target");
10627 return;
10630 DeleteTexturesHelper(1, &client_id);
10631 texture_ref = texture_manager()->Consume(client_id, texture);
10632 glBindTexture(target, texture_ref->service_id());
10634 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10635 unit.bind_target = target;
10636 switch (target) {
10637 case GL_TEXTURE_2D:
10638 unit.bound_texture_2d = texture_ref;
10639 break;
10640 case GL_TEXTURE_CUBE_MAP:
10641 unit.bound_texture_cube_map = texture_ref;
10642 break;
10643 case GL_TEXTURE_EXTERNAL_OES:
10644 unit.bound_texture_external_oes = texture_ref;
10645 break;
10646 case GL_TEXTURE_RECTANGLE_ARB:
10647 unit.bound_texture_rectangle_arb = texture_ref;
10648 break;
10649 default:
10650 NOTREACHED(); // Validation should prevent us getting here.
10651 break;
10655 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10656 uint32_t immediate_data_size,
10657 const void* cmd_data) {
10658 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
10659 *static_cast<
10660 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
10661 cmd_data);
10662 GLenum target = static_cast<GLenum>(c.target);
10663 uint32_t data_size;
10664 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
10665 return error::kOutOfBounds;
10667 if (data_size > immediate_data_size) {
10668 return error::kOutOfBounds;
10670 const GLbyte* mailbox =
10671 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
10672 if (!validators_->texture_bind_target.IsValid(target)) {
10673 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10674 "glCreateAndConsumeTextureCHROMIUM", target, "target");
10675 return error::kNoError;
10677 if (mailbox == NULL) {
10678 return error::kOutOfBounds;
10680 uint32_t client_id = c.client_id;
10681 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
10682 return error::kNoError;
10685 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
10686 const GLbyte* data, GLuint client_id) {
10687 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10688 "context", logger_.GetLogPrefix(),
10689 "mailbox[0]", static_cast<unsigned char>(data[0]));
10690 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10691 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10692 "passed a mailbox that was not "
10693 "generated by GenMailboxCHROMIUM.";
10695 TextureRef* texture_ref = GetTexture(client_id);
10696 if (texture_ref) {
10697 LOCAL_SET_GL_ERROR(
10698 GL_INVALID_OPERATION,
10699 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10700 return;
10702 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10703 if (!texture) {
10704 LOCAL_SET_GL_ERROR(
10705 GL_INVALID_OPERATION,
10706 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10707 return;
10709 if (texture->target() != target) {
10710 LOCAL_SET_GL_ERROR(
10711 GL_INVALID_OPERATION,
10712 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10713 return;
10716 IdAllocatorInterface* id_allocator =
10717 group_->GetIdAllocator(id_namespaces::kTextures);
10718 id_allocator->MarkAsUsed(client_id);
10720 texture_ref = texture_manager()->Consume(client_id, texture);
10723 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10724 GLsizei length, const GLchar* marker) {
10725 if (!marker) {
10726 marker = "";
10728 debug_marker_manager_.SetMarker(
10729 length ? std::string(marker, length) : std::string(marker));
10732 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10733 GLsizei length, const GLchar* marker) {
10734 if (!marker) {
10735 marker = "";
10737 std::string name = length ? std::string(marker, length) : std::string(marker);
10738 debug_marker_manager_.PushGroup(name);
10739 gpu_tracer_->Begin(name, kTraceGroupMarker);
10742 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10743 debug_marker_manager_.PopGroup();
10744 gpu_tracer_->End(kTraceGroupMarker);
10747 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10748 GLenum target, GLint image_id) {
10749 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10751 if (target == GL_TEXTURE_CUBE_MAP) {
10752 LOCAL_SET_GL_ERROR(
10753 GL_INVALID_ENUM,
10754 "glBindTexImage2DCHROMIUM", "invalid target");
10755 return;
10758 // Default target might be conceptually valid, but disallow it to avoid
10759 // accidents.
10760 TextureRef* texture_ref =
10761 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10762 if (!texture_ref) {
10763 LOCAL_SET_GL_ERROR(
10764 GL_INVALID_OPERATION,
10765 "glBindTexImage2DCHROMIUM", "no texture bound");
10766 return;
10769 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10770 if (!gl_image) {
10771 LOCAL_SET_GL_ERROR(
10772 GL_INVALID_OPERATION,
10773 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10774 return;
10778 ScopedGLErrorSuppressor suppressor(
10779 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10780 if (!gl_image->BindTexImage(target)) {
10781 LOCAL_SET_GL_ERROR(
10782 GL_INVALID_OPERATION,
10783 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10784 return;
10788 gfx::Size size = gl_image->GetSize();
10789 texture_manager()->SetLevelInfo(
10790 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10791 GL_RGBA, GL_UNSIGNED_BYTE, true);
10792 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10795 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10796 GLenum target, GLint image_id) {
10797 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10799 // Default target might be conceptually valid, but disallow it to avoid
10800 // accidents.
10801 TextureRef* texture_ref =
10802 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10803 if (!texture_ref) {
10804 LOCAL_SET_GL_ERROR(
10805 GL_INVALID_OPERATION,
10806 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10807 return;
10810 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10811 if (!gl_image) {
10812 LOCAL_SET_GL_ERROR(
10813 GL_INVALID_OPERATION,
10814 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10815 return;
10818 // Do nothing when image is not currently bound.
10819 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10820 return;
10823 ScopedGLErrorSuppressor suppressor(
10824 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10825 gl_image->ReleaseTexImage(target);
10828 texture_manager()->SetLevelInfo(
10829 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10830 GL_RGBA, GL_UNSIGNED_BYTE, false);
10833 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10834 uint32 immediate_data_size,
10835 const void* cmd_data) {
10836 const gles2::cmds::TraceBeginCHROMIUM& c =
10837 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
10838 Bucket* bucket = GetBucket(c.bucket_id);
10839 if (!bucket || bucket->size() == 0) {
10840 return error::kInvalidArguments;
10842 std::string command_name;
10843 if (!bucket->GetAsString(&command_name)) {
10844 return error::kInvalidArguments;
10846 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10847 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10848 LOCAL_SET_GL_ERROR(
10849 GL_INVALID_OPERATION,
10850 "glTraceBeginCHROMIUM", "unable to create begin trace");
10851 return error::kNoError;
10853 return error::kNoError;
10856 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10857 if (gpu_tracer_->CurrentName().empty()) {
10858 LOCAL_SET_GL_ERROR(
10859 GL_INVALID_OPERATION,
10860 "glTraceEndCHROMIUM", "no trace begin found");
10861 return;
10863 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10864 gpu_tracer_->End(kTraceCHROMIUM);
10867 void GLES2DecoderImpl::DoDrawBuffersEXT(
10868 GLsizei count, const GLenum* bufs) {
10869 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10870 LOCAL_SET_GL_ERROR(
10871 GL_INVALID_VALUE,
10872 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10873 return;
10876 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10877 if (framebuffer) {
10878 for (GLsizei i = 0; i < count; ++i) {
10879 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10880 bufs[i] != GL_NONE) {
10881 LOCAL_SET_GL_ERROR(
10882 GL_INVALID_OPERATION,
10883 "glDrawBuffersEXT",
10884 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10885 return;
10888 glDrawBuffersARB(count, bufs);
10889 framebuffer->SetDrawBuffers(count, bufs);
10890 } else { // backbuffer
10891 if (count > 1 ||
10892 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10893 LOCAL_SET_GL_ERROR(
10894 GL_INVALID_OPERATION,
10895 "glDrawBuffersEXT",
10896 "more than one buffer or bufs not GL_NONE or GL_BACK");
10897 return;
10899 GLenum mapped_buf = bufs[0];
10900 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10901 bufs[0] == GL_BACK) {
10902 mapped_buf = GL_COLOR_ATTACHMENT0;
10904 glDrawBuffersARB(count, &mapped_buf);
10905 group_->set_draw_buffer(bufs[0]);
10909 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
10910 group_->LoseContexts(other);
10911 reset_status_ = current;
10912 current_decoder_error_ = error::kLostContext;
10915 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
10916 const GLfloat* matrix) {
10917 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
10918 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
10919 if (!features().chromium_path_rendering) {
10920 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10921 "glMatrixLoadfCHROMIUM",
10922 "function not available");
10923 return;
10926 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
10927 ? state_.projection_matrix
10928 : state_.modelview_matrix;
10929 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
10930 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10931 // since the values of the _NV and _CHROMIUM tokens match.
10932 glMatrixLoadfEXT(matrix_mode, matrix);
10935 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
10936 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
10937 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
10939 if (!features().chromium_path_rendering) {
10940 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10941 "glMatrixLoadIdentityCHROMIUM",
10942 "function not available");
10943 return;
10946 static GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
10947 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
10948 0.0f, 0.0f, 0.0f, 1.0f};
10950 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
10951 ? state_.projection_matrix
10952 : state_.modelview_matrix;
10953 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
10954 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10955 // since the values of the _NV and _CHROMIUM tokens match.
10956 glMatrixLoadIdentityEXT(matrix_mode);
10959 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10960 const char* function_name,
10961 TextureRef* texture_ref,
10962 GLenum target,
10963 GLint level,
10964 const void * data) {
10965 // We only support async uploads to 2D textures for now.
10966 if (GL_TEXTURE_2D != target) {
10967 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10968 return false;
10970 // We only support uploads to level zero for now.
10971 if (level != 0) {
10972 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10973 return false;
10975 // A transfer buffer must be bound, even for asyncTexImage2D.
10976 if (data == NULL) {
10977 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10978 return false;
10980 // We only support one async transfer in progress.
10981 if (!texture_ref ||
10982 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10983 LOCAL_SET_GL_ERROR(
10984 GL_INVALID_OPERATION,
10985 function_name, "transfer already in progress");
10986 return false;
10988 return true;
10991 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10992 uint32 async_upload_token,
10993 uint32 sync_data_shm_id,
10994 uint32 sync_data_shm_offset) {
10995 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
10996 if (!buffer.get() ||
10997 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
10998 return base::Closure();
11000 AsyncMemoryParams mem_params(buffer,
11001 sync_data_shm_offset,
11002 sizeof(AsyncUploadSync));
11004 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
11005 new AsyncUploadTokenCompletionObserver(async_upload_token));
11007 return base::Bind(
11008 &AsyncPixelTransferManager::AsyncNotifyCompletion,
11009 base::Unretained(GetAsyncPixelTransferManager()),
11010 mem_params,
11011 observer);
11014 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
11015 uint32 immediate_data_size,
11016 const void* cmd_data) {
11017 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
11018 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
11019 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
11020 GLenum target = static_cast<GLenum>(c.target);
11021 GLint level = static_cast<GLint>(c.level);
11022 GLenum internal_format = static_cast<GLenum>(c.internalformat);
11023 GLsizei width = static_cast<GLsizei>(c.width);
11024 GLsizei height = static_cast<GLsizei>(c.height);
11025 GLint border = static_cast<GLint>(c.border);
11026 GLenum format = static_cast<GLenum>(c.format);
11027 GLenum type = static_cast<GLenum>(c.type);
11028 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
11029 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
11030 uint32 pixels_size;
11031 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11032 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11033 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11035 base::ScopedClosureRunner scoped_completion_callback;
11036 if (async_upload_token) {
11037 base::Closure completion_closure =
11038 AsyncUploadTokenCompletionClosure(async_upload_token,
11039 sync_data_shm_id,
11040 sync_data_shm_offset);
11041 if (completion_closure.is_null())
11042 return error::kInvalidArguments;
11044 scoped_completion_callback.Reset(completion_closure);
11047 // TODO(epenner): Move this and copies of this memory validation
11048 // into ValidateTexImage2D step.
11049 if (!GLES2Util::ComputeImageDataSizes(
11050 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
11051 NULL)) {
11052 return error::kOutOfBounds;
11054 const void* pixels = NULL;
11055 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
11056 pixels = GetSharedMemoryAs<const void*>(
11057 pixels_shm_id, pixels_shm_offset, pixels_size);
11058 if (!pixels) {
11059 return error::kOutOfBounds;
11063 TextureManager::DoTextImage2DArguments args = {
11064 target, level, internal_format, width, height, border, format, type,
11065 pixels, pixels_size};
11066 TextureRef* texture_ref;
11067 // All the normal glTexSubImage2D validation.
11068 if (!texture_manager()->ValidateTexImage2D(
11069 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
11070 return error::kNoError;
11073 // Extra async validation.
11074 Texture* texture = texture_ref->texture();
11075 if (!ValidateAsyncTransfer(
11076 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
11077 return error::kNoError;
11079 // Don't allow async redefinition of a textures.
11080 if (texture->IsDefined()) {
11081 LOCAL_SET_GL_ERROR(
11082 GL_INVALID_OPERATION,
11083 "glAsyncTexImage2DCHROMIUM", "already defined");
11084 return error::kNoError;
11087 if (!EnsureGPUMemoryAvailable(pixels_size)) {
11088 LOCAL_SET_GL_ERROR(
11089 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
11090 return error::kNoError;
11093 // Setup the parameters.
11094 AsyncTexImage2DParams tex_params = {
11095 target, level, static_cast<GLenum>(internal_format),
11096 width, height, border, format, type};
11097 AsyncMemoryParams mem_params(
11098 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
11100 // Set up the async state if needed, and make the texture
11101 // immutable so the async state stays valid. The level info
11102 // is set up lazily when the transfer completes.
11103 AsyncPixelTransferDelegate* delegate =
11104 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
11105 tex_params);
11106 texture->SetImmutable(true);
11108 delegate->AsyncTexImage2D(
11109 tex_params,
11110 mem_params,
11111 base::Bind(&TextureManager::SetLevelInfoFromParams,
11112 // The callback is only invoked if the transfer delegate still
11113 // exists, which implies through manager->texture_ref->state
11114 // ownership that both of these pointers are valid.
11115 base::Unretained(texture_manager()),
11116 base::Unretained(texture_ref),
11117 tex_params));
11118 return error::kNoError;
11121 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
11122 uint32 immediate_data_size,
11123 const void* cmd_data) {
11124 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
11125 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
11126 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
11127 GLenum target = static_cast<GLenum>(c.target);
11128 GLint level = static_cast<GLint>(c.level);
11129 GLint xoffset = static_cast<GLint>(c.xoffset);
11130 GLint yoffset = static_cast<GLint>(c.yoffset);
11131 GLsizei width = static_cast<GLsizei>(c.width);
11132 GLsizei height = static_cast<GLsizei>(c.height);
11133 GLenum format = static_cast<GLenum>(c.format);
11134 GLenum type = static_cast<GLenum>(c.type);
11135 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11136 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11137 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11139 base::ScopedClosureRunner scoped_completion_callback;
11140 if (async_upload_token) {
11141 base::Closure completion_closure =
11142 AsyncUploadTokenCompletionClosure(async_upload_token,
11143 sync_data_shm_id,
11144 sync_data_shm_offset);
11145 if (completion_closure.is_null())
11146 return error::kInvalidArguments;
11148 scoped_completion_callback.Reset(completion_closure);
11151 // TODO(epenner): Move this and copies of this memory validation
11152 // into ValidateTexSubImage2D step.
11153 uint32 data_size;
11154 if (!GLES2Util::ComputeImageDataSizes(
11155 width, height, format, type, state_.unpack_alignment, &data_size,
11156 NULL, NULL)) {
11157 return error::kOutOfBounds;
11159 const void* pixels = GetSharedMemoryAs<const void*>(
11160 c.data_shm_id, c.data_shm_offset, data_size);
11162 // All the normal glTexSubImage2D validation.
11163 error::Error error = error::kNoError;
11164 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
11165 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
11166 return error;
11169 // Extra async validation.
11170 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11171 &state_, target);
11172 Texture* texture = texture_ref->texture();
11173 if (!ValidateAsyncTransfer(
11174 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
11175 return error::kNoError;
11177 // Guarantee async textures are always 'cleared' as follows:
11178 // - AsyncTexImage2D can not redefine an existing texture
11179 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
11180 // - AsyncTexSubImage2D clears synchronously if not already cleared.
11181 // - Textures become immutable after an async call.
11182 // This way we know in all cases that an async texture is always clear.
11183 if (!texture->SafeToRenderFrom()) {
11184 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
11185 target, level)) {
11186 LOCAL_SET_GL_ERROR(
11187 GL_OUT_OF_MEMORY,
11188 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
11189 return error::kNoError;
11193 // Setup the parameters.
11194 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
11195 width, height, format, type};
11196 AsyncMemoryParams mem_params(
11197 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
11198 AsyncPixelTransferDelegate* delegate =
11199 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11200 if (!delegate) {
11201 // TODO(epenner): We may want to enforce exclusive use
11202 // of async APIs in which case this should become an error,
11203 // (the texture should have been async defined).
11204 AsyncTexImage2DParams define_params = {target, level,
11205 0, 0, 0, 0, 0, 0};
11206 texture->GetLevelSize(target, level, &define_params.width,
11207 &define_params.height);
11208 texture->GetLevelType(target, level, &define_params.type,
11209 &define_params.internal_format);
11210 // Set up the async state if needed, and make the texture
11211 // immutable so the async state stays valid.
11212 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
11213 texture_ref, define_params);
11214 texture->SetImmutable(true);
11217 delegate->AsyncTexSubImage2D(tex_params, mem_params);
11218 return error::kNoError;
11221 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
11222 uint32 immediate_data_size,
11223 const void* cmd_data) {
11224 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
11225 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
11226 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11227 GLenum target = static_cast<GLenum>(c.target);
11229 if (GL_TEXTURE_2D != target) {
11230 LOCAL_SET_GL_ERROR(
11231 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
11232 return error::kNoError;
11234 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11235 &state_, target);
11236 if (!texture_ref) {
11237 LOCAL_SET_GL_ERROR(
11238 GL_INVALID_OPERATION,
11239 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
11240 return error::kNoError;
11242 AsyncPixelTransferDelegate* delegate =
11243 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11244 if (!delegate) {
11245 LOCAL_SET_GL_ERROR(
11246 GL_INVALID_OPERATION,
11247 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
11248 return error::kNoError;
11250 delegate->WaitForTransferCompletion();
11251 ProcessFinishedAsyncTransfers();
11252 return error::kNoError;
11255 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
11256 uint32 immediate_data_size,
11257 const void* data) {
11258 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11260 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
11261 ProcessFinishedAsyncTransfers();
11262 return error::kNoError;
11265 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
11266 TextureRef* texture_ref) {
11267 Texture* texture = texture_ref->texture();
11268 DoDidUseTexImageIfNeeded(texture, texture->target());
11271 void GLES2DecoderImpl::OnOutOfMemoryError() {
11272 if (lose_context_when_out_of_memory_) {
11273 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
11274 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB);
11278 // Include the auto-generated part of this file. We split this because it means
11279 // we can easily edit the non-auto generated parts right here in this file
11280 // instead of having to edit some template or the code generator.
11281 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
11283 } // namespace gles2
11284 } // namespace gpu