Android: Enable 'crash GPU process on context lost' WAR for Mali-400
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
bloba14f72e11199ea51c4abdb21c359217f7eb4c6cc
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 <cmath>
11 #include <list>
12 #include <map>
13 #include <queue>
14 #include <stack>
15 #include <string>
16 #include <vector>
18 #include "base/at_exit.h"
19 #include "base/bind.h"
20 #include "base/callback_helpers.h"
21 #include "base/command_line.h"
22 #include "base/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "base/trace_event/trace_event.h"
27 #include "base/trace_event/trace_event_synthetic_delay.h"
28 #include "build/build_config.h"
29 #define GLES2_GPU_SERVICE 1
30 #include "gpu/command_buffer/common/debug_marker_manager.h"
31 #include "gpu/command_buffer/common/gles2_cmd_format.h"
32 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
33 #include "gpu/command_buffer/common/id_allocator.h"
34 #include "gpu/command_buffer/common/mailbox.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
36 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
37 #include "gpu/command_buffer/service/buffer_manager.h"
38 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
39 #include "gpu/command_buffer/service/context_group.h"
40 #include "gpu/command_buffer/service/context_state.h"
41 #include "gpu/command_buffer/service/error_state.h"
42 #include "gpu/command_buffer/service/feature_info.h"
43 #include "gpu/command_buffer/service/framebuffer_manager.h"
44 #include "gpu/command_buffer/service/gl_utils.h"
45 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
46 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
47 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
48 #include "gpu/command_buffer/service/gpu_state_tracer.h"
49 #include "gpu/command_buffer/service/gpu_switches.h"
50 #include "gpu/command_buffer/service/gpu_tracer.h"
51 #include "gpu/command_buffer/service/image_manager.h"
52 #include "gpu/command_buffer/service/mailbox_manager.h"
53 #include "gpu/command_buffer/service/memory_tracking.h"
54 #include "gpu/command_buffer/service/program_manager.h"
55 #include "gpu/command_buffer/service/query_manager.h"
56 #include "gpu/command_buffer/service/renderbuffer_manager.h"
57 #include "gpu/command_buffer/service/shader_manager.h"
58 #include "gpu/command_buffer/service/shader_translator.h"
59 #include "gpu/command_buffer/service/shader_translator_cache.h"
60 #include "gpu/command_buffer/service/texture_manager.h"
61 #include "gpu/command_buffer/service/valuebuffer_manager.h"
62 #include "gpu/command_buffer/service/vertex_array_manager.h"
63 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
64 #include "third_party/smhasher/src/City.h"
65 #include "ui/gl/gl_fence.h"
66 #include "ui/gl/gl_image.h"
67 #include "ui/gl/gl_implementation.h"
68 #include "ui/gl/gl_surface.h"
70 #if defined(OS_MACOSX)
71 #include <IOSurface/IOSurfaceAPI.h>
72 // Note that this must be included after gl_bindings.h to avoid conflicts.
73 #include <OpenGL/CGLIOSurface.h>
74 #endif
76 #if defined(OS_WIN)
77 #include "base/win/win_util.h"
78 #endif
80 namespace gpu {
81 namespace gles2 {
83 namespace {
85 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
86 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
87 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
88 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
90 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
91 0.0f, 1.0f, 0.0f, 0.0f,
92 0.0f, 0.0f, 1.0f, 0.0f,
93 0.0f, 0.0f, 0.0f, 1.0f};
95 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
96 GLint rangeMax,
97 GLint precision) {
98 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
101 void GetShaderPrecisionFormatImpl(GLenum shader_type,
102 GLenum precision_type,
103 GLint* range, GLint* precision) {
104 switch (precision_type) {
105 case GL_LOW_INT:
106 case GL_MEDIUM_INT:
107 case GL_HIGH_INT:
108 // These values are for a 32-bit twos-complement integer format.
109 range[0] = 31;
110 range[1] = 30;
111 *precision = 0;
112 break;
113 case GL_LOW_FLOAT:
114 case GL_MEDIUM_FLOAT:
115 case GL_HIGH_FLOAT:
116 // These values are for an IEEE single-precision floating-point format.
117 range[0] = 127;
118 range[1] = 127;
119 *precision = 23;
120 break;
121 default:
122 NOTREACHED();
123 break;
126 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
127 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
128 // This function is sometimes defined even though it's really just
129 // a stub, so we need to set range and precision as if it weren't
130 // defined before calling it.
131 // On Mac OS with some GPUs, calling this generates a
132 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 // platforms.
134 glGetShaderPrecisionFormat(shader_type, precision_type,
135 range, precision);
137 // TODO(brianderson): Make the following official workarounds.
139 // Some drivers have bugs where they report the ranges as a negative number.
140 // Taking the absolute value here shouldn't hurt because negative numbers
141 // aren't expected anyway.
142 range[0] = abs(range[0]);
143 range[1] = abs(range[1]);
145 // If the driver reports a precision for highp float that isn't actually
146 // highp, don't pretend like it's supported because shader compilation will
147 // fail anyway.
148 if (precision_type == GL_HIGH_FLOAT &&
149 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
150 range[0] = 0;
151 range[1] = 0;
152 *precision = 0;
157 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
158 switch (plane_transform) {
159 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
160 return gfx::OVERLAY_TRANSFORM_NONE;
161 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
162 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
163 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
164 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
165 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
166 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
167 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
168 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
169 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
170 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
171 default:
172 return gfx::OVERLAY_TRANSFORM_INVALID;
176 template <typename MANAGER_TYPE, typename OBJECT_TYPE>
177 GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
178 DCHECK(manager);
179 GLuint client_id = 0;
180 if (object) {
181 manager->GetClientId(object->service_id(), &client_id);
183 return client_id;
186 struct Vec4f {
187 explicit Vec4f(const Vec4& data) {
188 data.GetValues(v);
191 GLfloat v[4];
194 } // namespace
196 class GLES2DecoderImpl;
198 // Local versions of the SET_GL_ERROR macros
199 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
200 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
201 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
202 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
203 function_name, value, label)
204 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
205 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
206 function_name, pname)
207 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
208 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
209 function_name)
210 #define LOCAL_PEEK_GL_ERROR(function_name) \
211 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
212 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
213 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
214 #define LOCAL_PERFORMANCE_WARNING(msg) \
215 PerformanceWarning(__FILE__, __LINE__, msg)
216 #define LOCAL_RENDER_WARNING(msg) \
217 RenderWarning(__FILE__, __LINE__, msg)
219 // Check that certain assumptions the code makes are true. There are places in
220 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
221 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
222 // a few others) are 32bits. If they are not 32bits the code will have to change
223 // to call those GL functions with service side memory and then copy the results
224 // to shared memory, converting the sizes.
225 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
226 "GLint should be the same size as uint32");
227 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
228 "GLsizei should be the same size as uint32");
229 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
230 "GLfloat should be the same size as float");
232 // TODO(kbr): the use of this anonymous namespace core dumps the
233 // linker on Mac OS X 10.6 when the symbol ordering file is used
234 // namespace {
236 // Returns the address of the first byte after a struct.
237 template <typename T>
238 const void* AddressAfterStruct(const T& pod) {
239 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
242 // Returns the address of the frst byte after the struct or NULL if size >
243 // immediate_data_size.
244 template <typename RETURN_TYPE, typename COMMAND_TYPE>
245 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
246 uint32 size,
247 uint32 immediate_data_size) {
248 return (size <= immediate_data_size) ?
249 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
250 NULL;
253 // Computes the data size for certain gl commands like glUniform.
254 bool ComputeDataSize(
255 GLuint count,
256 size_t size,
257 unsigned int elements_per_unit,
258 uint32* dst) {
259 uint32 value;
260 if (!SafeMultiplyUint32(count, size, &value)) {
261 return false;
263 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
264 return false;
266 *dst = value;
267 return true;
270 // Return true if a character belongs to the ASCII subset as defined in
271 // GLSL ES 1.0 spec section 3.1.
272 static bool CharacterIsValidForGLES(unsigned char c) {
273 // Printing characters are valid except " $ ` @ \ ' DEL.
274 if (c >= 32 && c <= 126 &&
275 c != '"' &&
276 c != '$' &&
277 c != '`' &&
278 c != '@' &&
279 c != '\\' &&
280 c != '\'') {
281 return true;
283 // Horizontal tab, line feed, vertical tab, form feed, carriage return
284 // are also valid.
285 if (c >= 9 && c <= 13) {
286 return true;
289 return false;
292 static bool StringIsValidForGLES(const char* str) {
293 for (; *str; ++str) {
294 if (!CharacterIsValidForGLES(*str)) {
295 return false;
298 return true;
301 // This class prevents any GL errors that occur when it is in scope from
302 // being reported to the client.
303 class ScopedGLErrorSuppressor {
304 public:
305 explicit ScopedGLErrorSuppressor(
306 const char* function_name, ErrorState* error_state);
307 ~ScopedGLErrorSuppressor();
308 private:
309 const char* function_name_;
310 ErrorState* error_state_;
311 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
314 // Temporarily changes a decoder's bound texture and restore it when this
315 // object goes out of scope. Also temporarily switches to using active texture
316 // unit zero in case the client has changed that to something invalid.
317 class ScopedTextureBinder {
318 public:
319 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
320 ~ScopedTextureBinder();
322 private:
323 ContextState* state_;
324 GLenum target_;
325 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
328 // Temporarily changes a decoder's bound render buffer and restore it when this
329 // object goes out of scope.
330 class ScopedRenderBufferBinder {
331 public:
332 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
333 ~ScopedRenderBufferBinder();
335 private:
336 ContextState* state_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
340 // Temporarily changes a decoder's bound frame buffer and restore it when this
341 // object goes out of scope.
342 class ScopedFrameBufferBinder {
343 public:
344 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
345 ~ScopedFrameBufferBinder();
347 private:
348 GLES2DecoderImpl* decoder_;
349 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
352 // Temporarily changes a decoder's bound frame buffer to a resolved version of
353 // the multisampled offscreen render buffer if that buffer is multisampled, and,
354 // if it is bound or enforce_internal_framebuffer is true. If internal is
355 // true, the resolved framebuffer is not visible to the parent.
356 class ScopedResolvedFrameBufferBinder {
357 public:
358 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
359 bool enforce_internal_framebuffer,
360 bool internal);
361 ~ScopedResolvedFrameBufferBinder();
363 private:
364 GLES2DecoderImpl* decoder_;
365 bool resolve_and_bind_;
366 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
369 class ScopedModifyPixels {
370 public:
371 explicit ScopedModifyPixels(TextureRef* ref);
372 ~ScopedModifyPixels();
374 private:
375 TextureRef* ref_;
378 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
379 if (ref_)
380 ref_->texture()->OnWillModifyPixels();
383 ScopedModifyPixels::~ScopedModifyPixels() {
384 if (ref_)
385 ref_->texture()->OnDidModifyPixels();
388 class ScopedRenderTo {
389 public:
390 explicit ScopedRenderTo(Framebuffer* framebuffer);
391 ~ScopedRenderTo();
393 private:
394 const Framebuffer* framebuffer_;
397 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
398 : framebuffer_(framebuffer) {
399 if (framebuffer)
400 framebuffer_->OnWillRenderTo();
403 ScopedRenderTo::~ScopedRenderTo() {
404 if (framebuffer_)
405 framebuffer_->OnDidRenderTo();
408 // Encapsulates an OpenGL texture.
409 class BackTexture {
410 public:
411 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
412 ~BackTexture();
414 // Create a new render texture.
415 void Create();
417 // Set the initial size and format of a render texture or resize it.
418 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
420 // Copy the contents of the currently bound frame buffer.
421 void Copy(const gfx::Size& size, GLenum format);
423 // Destroy the render texture. This must be explicitly called before
424 // destroying this object.
425 void Destroy();
427 // Invalidate the texture. This can be used when a context is lost and it is
428 // not possible to make it current in order to free the resource.
429 void Invalidate();
431 GLuint id() const {
432 return id_;
435 gfx::Size size() const {
436 return size_;
439 private:
440 MemoryTypeTracker memory_tracker_;
441 ContextState* state_;
442 size_t bytes_allocated_;
443 GLuint id_;
444 gfx::Size size_;
445 DISALLOW_COPY_AND_ASSIGN(BackTexture);
448 // Encapsulates an OpenGL render buffer of any format.
449 class BackRenderbuffer {
450 public:
451 explicit BackRenderbuffer(
452 RenderbufferManager* renderbuffer_manager,
453 MemoryTracker* memory_tracker,
454 ContextState* state);
455 ~BackRenderbuffer();
457 // Create a new render buffer.
458 void Create();
460 // Set the initial size and format of a render buffer or resize it.
461 bool AllocateStorage(const FeatureInfo* feature_info,
462 const gfx::Size& size,
463 GLenum format,
464 GLsizei samples);
466 // Destroy the render buffer. This must be explicitly called before destroying
467 // this object.
468 void Destroy();
470 // Invalidate the render buffer. This can be used when a context is lost and
471 // it is not possible to make it current in order to free the resource.
472 void Invalidate();
474 GLuint id() const {
475 return id_;
478 private:
479 RenderbufferManager* renderbuffer_manager_;
480 MemoryTypeTracker memory_tracker_;
481 ContextState* state_;
482 size_t bytes_allocated_;
483 GLuint id_;
484 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
487 // Encapsulates an OpenGL frame buffer.
488 class BackFramebuffer {
489 public:
490 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
491 ~BackFramebuffer();
493 // Create a new frame buffer.
494 void Create();
496 // Attach a color render buffer to a frame buffer.
497 void AttachRenderTexture(BackTexture* texture);
499 // Attach a render buffer to a frame buffer. Note that this unbinds any
500 // currently bound frame buffer.
501 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
503 // Destroy the frame buffer. This must be explicitly called before destroying
504 // this object.
505 void Destroy();
507 // Invalidate the frame buffer. This can be used when a context is lost and it
508 // is not possible to make it current in order to free the resource.
509 void Invalidate();
511 // See glCheckFramebufferStatusEXT.
512 GLenum CheckStatus();
514 GLuint id() const {
515 return id_;
518 private:
519 GLES2DecoderImpl* decoder_;
520 GLuint id_;
521 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
524 struct FenceCallback {
525 FenceCallback()
526 : fence(gfx::GLFence::Create()) {
527 DCHECK(fence);
529 std::vector<base::Closure> callbacks;
530 scoped_ptr<gfx::GLFence> fence;
533 class AsyncUploadTokenCompletionObserver
534 : public AsyncPixelTransferCompletionObserver {
535 public:
536 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
537 : async_upload_token_(async_upload_token) {
540 void DidComplete(const AsyncMemoryParams& mem_params) override {
541 DCHECK(mem_params.buffer().get());
542 void* data = mem_params.GetDataAddress();
543 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
544 sync->SetAsyncUploadToken(async_upload_token_);
547 private:
548 ~AsyncUploadTokenCompletionObserver() override {}
550 uint32 async_upload_token_;
552 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
555 // } // anonymous namespace.
557 // static
558 const unsigned int GLES2Decoder::kDefaultStencilMask =
559 static_cast<unsigned int>(-1);
561 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
562 uint32* service_texture_id) {
563 return false;
566 GLES2Decoder::GLES2Decoder()
567 : initialized_(false),
568 debug_(false),
569 log_commands_(false),
570 unsafe_es3_apis_enabled_(false) {
573 GLES2Decoder::~GLES2Decoder() {
576 void GLES2Decoder::BeginDecoding() {}
578 void GLES2Decoder::EndDecoding() {}
580 // This class implements GLES2Decoder so we don't have to expose all the GLES2
581 // cmd stuff to outside this class.
582 class GLES2DecoderImpl : public GLES2Decoder,
583 public FramebufferManager::TextureDetachObserver,
584 public ErrorStateClient {
585 public:
586 explicit GLES2DecoderImpl(ContextGroup* group);
587 ~GLES2DecoderImpl() override;
589 // Overridden from AsyncAPIInterface.
590 Error DoCommand(unsigned int command,
591 unsigned int arg_count,
592 const void* args) override;
594 error::Error DoCommands(unsigned int num_commands,
595 const void* buffer,
596 int num_entries,
597 int* entries_processed) override;
599 template <bool DebugImpl>
600 error::Error DoCommandsImpl(unsigned int num_commands,
601 const void* buffer,
602 int num_entries,
603 int* entries_processed);
605 // Overridden from AsyncAPIInterface.
606 const char* GetCommandName(unsigned int command_id) const override;
608 // Overridden from GLES2Decoder.
609 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
610 const scoped_refptr<gfx::GLContext>& context,
611 bool offscreen,
612 const gfx::Size& offscreen_size,
613 const DisallowedFeatures& disallowed_features,
614 const std::vector<int32>& attribs) override;
615 void Destroy(bool have_context) override;
616 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
617 void ProduceFrontBuffer(const Mailbox& mailbox) override;
618 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
619 void UpdateParentTextureInfo();
620 bool MakeCurrent() override;
621 GLES2Util* GetGLES2Util() override { return &util_; }
622 gfx::GLContext* GetGLContext() override { return context_.get(); }
623 ContextGroup* GetContextGroup() override { return group_.get(); }
624 Capabilities GetCapabilities() override;
625 void RestoreState(const ContextState* prev_state) override;
627 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
628 void RestoreAllTextureUnitBindings(
629 const ContextState* prev_state) const override {
630 state_.RestoreAllTextureUnitBindings(prev_state);
632 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
633 state_.RestoreActiveTextureUnitBinding(target);
635 void RestoreBufferBindings() const override {
636 state_.RestoreBufferBindings();
638 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
639 void RestoreProgramBindings() const override {
640 state_.RestoreProgramBindings();
642 void RestoreTextureUnitBindings(unsigned unit) const override {
643 state_.RestoreTextureUnitBindings(unit, NULL);
645 void RestoreFramebufferBindings() const override;
646 void RestoreRenderbufferBindings() override;
647 void RestoreTextureState(unsigned service_id) const override;
649 void ClearAllAttributes() const override;
650 void RestoreAllAttributes() const override;
652 QueryManager* GetQueryManager() override { return query_manager_.get(); }
653 VertexArrayManager* GetVertexArrayManager() override {
654 return vertex_array_manager_.get();
656 ImageManager* GetImageManager() override { return image_manager_.get(); }
658 ValuebufferManager* GetValuebufferManager() override {
659 return valuebuffer_manager();
662 bool ProcessPendingQueries(bool did_finish) override;
664 bool HasMoreIdleWork() override;
665 void PerformIdleWork() override;
667 void WaitForReadPixels(base::Closure callback) override;
669 void SetResizeCallback(
670 const base::Callback<void(gfx::Size, float)>& callback) override;
672 Logger* GetLogger() override;
674 void BeginDecoding() override;
675 void EndDecoding() override;
677 ErrorState* GetErrorState() override;
678 const ContextState* GetContextState() override { return &state_; }
680 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
681 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
683 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
684 void ResetAsyncPixelTransferManagerForTest() override;
685 void SetAsyncPixelTransferManagerForTest(
686 AsyncPixelTransferManager* manager) override;
687 void SetIgnoreCachedStateForTest(bool ignore) override;
688 void SetAllowExit(bool allow_exit) override;
689 void ProcessFinishedAsyncTransfers();
691 bool GetServiceTextureId(uint32 client_texture_id,
692 uint32* service_texture_id) override;
694 uint32 GetTextureUploadCount() override;
695 base::TimeDelta GetTotalTextureUploadTime() override;
696 base::TimeDelta GetTotalProcessingCommandsTime() override;
697 void AddProcessingCommandsTime(base::TimeDelta) override;
699 // Restores the current state to the user's settings.
700 void RestoreCurrentFramebufferBindings();
702 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
703 void ApplyDirtyState();
705 // These check the state of the currently bound framebuffer or the
706 // backbuffer if no framebuffer is bound.
707 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
708 // check with all attached and enabled color attachments.
709 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
710 bool BoundFramebufferHasDepthAttachment();
711 bool BoundFramebufferHasStencilAttachment();
713 error::ContextLostReason GetContextLostReason() override;
715 // Overridden from FramebufferManager::TextureDetachObserver:
716 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
718 // Overriden from ErrorStateClient.
719 void OnContextLostError() override;
720 void OnOutOfMemoryError() override;
722 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
723 void EnsureRenderbufferBound();
725 // Helpers to facilitate calling into compatible extensions.
726 static void RenderbufferStorageMultisampleHelper(
727 const FeatureInfo* feature_info,
728 GLenum target,
729 GLsizei samples,
730 GLenum internal_format,
731 GLsizei width,
732 GLsizei height);
734 void BlitFramebufferHelper(GLint srcX0,
735 GLint srcY0,
736 GLint srcX1,
737 GLint srcY1,
738 GLint dstX0,
739 GLint dstY0,
740 GLint dstX1,
741 GLint dstY1,
742 GLbitfield mask,
743 GLenum filter);
745 private:
746 friend class ScopedFrameBufferBinder;
747 friend class ScopedResolvedFrameBufferBinder;
748 friend class BackFramebuffer;
750 // Initialize or re-initialize the shader translator.
751 bool InitializeShaderTranslator();
753 void UpdateCapabilities();
755 // Helpers for the glGen and glDelete functions.
756 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
757 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
758 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
759 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
760 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
761 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
762 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
763 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
764 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
765 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
766 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
767 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
768 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
769 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
771 // Helper for async upload token completion notification callback.
772 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
773 uint32 sync_data_shm_id,
774 uint32 sync_data_shm_offset);
778 // Workarounds
779 void OnFboChanged() const;
780 void OnUseFramebuffer() const;
782 error::ContextLostReason GetContextLostReasonFromResetStatus(
783 GLenum reset_status) const;
785 // TODO(gman): Cache these pointers?
786 BufferManager* buffer_manager() {
787 return group_->buffer_manager();
790 RenderbufferManager* renderbuffer_manager() {
791 return group_->renderbuffer_manager();
794 FramebufferManager* framebuffer_manager() {
795 return group_->framebuffer_manager();
798 ValuebufferManager* valuebuffer_manager() {
799 return group_->valuebuffer_manager();
802 ProgramManager* program_manager() {
803 return group_->program_manager();
806 ShaderManager* shader_manager() {
807 return group_->shader_manager();
810 ShaderTranslatorCache* shader_translator_cache() {
811 return group_->shader_translator_cache();
814 const TextureManager* texture_manager() const {
815 return group_->texture_manager();
818 TextureManager* texture_manager() {
819 return group_->texture_manager();
822 MailboxManager* mailbox_manager() {
823 return group_->mailbox_manager();
826 ImageManager* image_manager() { return image_manager_.get(); }
828 VertexArrayManager* vertex_array_manager() {
829 return vertex_array_manager_.get();
832 MemoryTracker* memory_tracker() {
833 return group_->memory_tracker();
836 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
837 MemoryTracker* tracker = memory_tracker();
838 if (tracker) {
839 return tracker->EnsureGPUMemoryAvailable(estimated_size);
841 return true;
844 bool IsOffscreenBufferMultisampled() const {
845 return offscreen_target_samples_ > 1;
848 // Creates a Texture for the given texture.
849 TextureRef* CreateTexture(
850 GLuint client_id, GLuint service_id) {
851 return texture_manager()->CreateTexture(client_id, service_id);
854 // Gets the texture info for the given texture. Returns NULL if none exists.
855 TextureRef* GetTexture(GLuint client_id) const {
856 return texture_manager()->GetTexture(client_id);
859 // Deletes the texture info for the given texture.
860 void RemoveTexture(GLuint client_id) {
861 texture_manager()->RemoveTexture(client_id);
864 // Get the size (in pixels) of the currently bound frame buffer (either FBO
865 // or regular back buffer).
866 gfx::Size GetBoundReadFrameBufferSize();
868 // Get the format of the currently bound frame buffer (either FBO or regular
869 // back buffer)
870 GLenum GetBoundReadFrameBufferTextureType();
871 GLenum GetBoundReadFrameBufferInternalFormat();
872 GLenum GetBoundDrawFrameBufferInternalFormat();
874 // Wrapper for CompressedTexImage2D commands.
875 error::Error DoCompressedTexImage2D(
876 GLenum target,
877 GLint level,
878 GLenum internal_format,
879 GLsizei width,
880 GLsizei height,
881 GLint border,
882 GLsizei image_size,
883 const void* data);
885 // Wrapper for CompressedTexImage3D commands.
886 error::Error DoCompressedTexImage3D(
887 GLenum target,
888 GLint level,
889 GLenum internal_format,
890 GLsizei width,
891 GLsizei height,
892 GLsizei depth,
893 GLint border,
894 GLsizei image_size,
895 const void* data);
897 // Wrapper for CompressedTexSubImage2D.
898 void DoCompressedTexSubImage2D(
899 GLenum target,
900 GLint level,
901 GLint xoffset,
902 GLint yoffset,
903 GLsizei width,
904 GLsizei height,
905 GLenum format,
906 GLsizei imageSize,
907 const void * data);
909 // Wrapper for CompressedTexSubImage3D.
910 void DoCompressedTexSubImage3D(
911 GLenum target,
912 GLint level,
913 GLint xoffset,
914 GLint yoffset,
915 GLint zoffset,
916 GLsizei width,
917 GLsizei height,
918 GLsizei depth,
919 GLenum format,
920 GLsizei image_size,
921 const void* data);
923 // Wrapper for CopyTexImage2D.
924 void DoCopyTexImage2D(
925 GLenum target,
926 GLint level,
927 GLenum internal_format,
928 GLint x,
929 GLint y,
930 GLsizei width,
931 GLsizei height,
932 GLint border);
934 // Wrapper for SwapBuffers.
935 void DoSwapBuffers();
937 // Wrapper for SwapInterval.
938 void DoSwapInterval(int interval);
940 // Wrapper for CopyTexSubImage2D.
941 void DoCopyTexSubImage2D(
942 GLenum target,
943 GLint level,
944 GLint xoffset,
945 GLint yoffset,
946 GLint x,
947 GLint y,
948 GLsizei width,
949 GLsizei height);
951 // Validation for TexSubImage2D.
952 bool ValidateTexSubImage2D(
953 error::Error* error,
954 const char* function_name,
955 GLenum target,
956 GLint level,
957 GLint xoffset,
958 GLint yoffset,
959 GLsizei width,
960 GLsizei height,
961 GLenum format,
962 GLenum type,
963 const void * data);
965 // Wrapper for TexSubImage2D.
966 error::Error DoTexSubImage2D(
967 GLenum target,
968 GLint level,
969 GLint xoffset,
970 GLint yoffset,
971 GLsizei width,
972 GLsizei height,
973 GLenum format,
974 GLenum type,
975 const void * data);
977 // Wrapper for TexSubImage3D.
978 error::Error DoTexSubImage3D(
979 GLenum target,
980 GLint level,
981 GLint xoffset,
982 GLint yoffset,
983 GLint zoffset,
984 GLsizei width,
985 GLsizei height,
986 GLsizei depth,
987 GLenum format,
988 GLenum type,
989 const void * data);
991 // Extra validation for async tex(Sub)Image2D.
992 bool ValidateAsyncTransfer(
993 const char* function_name,
994 TextureRef* texture_ref,
995 GLenum target,
996 GLint level,
997 const void * data);
999 // Wrapper for TexImageIOSurface2DCHROMIUM.
1000 void DoTexImageIOSurface2DCHROMIUM(
1001 GLenum target,
1002 GLsizei width,
1003 GLsizei height,
1004 GLuint io_surface_id,
1005 GLuint plane);
1007 void DoCopyTextureCHROMIUM(GLenum target,
1008 GLuint source_id,
1009 GLuint dest_id,
1010 GLenum internal_format,
1011 GLenum dest_type);
1013 void DoCopySubTextureCHROMIUM(GLenum target,
1014 GLuint source_id,
1015 GLuint dest_id,
1016 GLint xoffset,
1017 GLint yoffset,
1018 GLint x,
1019 GLint y,
1020 GLsizei width,
1021 GLsizei height);
1023 // Wrapper for TexStorage2DEXT.
1024 void DoTexStorage2DEXT(
1025 GLenum target,
1026 GLint levels,
1027 GLenum internal_format,
1028 GLsizei width,
1029 GLsizei height);
1031 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1032 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1033 const GLbyte* key);
1034 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
1035 GLenum target, const GLbyte* data);
1037 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1038 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1039 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1040 GLuint client_id);
1042 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1043 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1044 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1045 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1046 void DoUniformValueBufferCHROMIUM(GLint location,
1047 GLenum target,
1048 GLenum subscription);
1050 void DoBindTexImage2DCHROMIUM(
1051 GLenum target,
1052 GLint image_id);
1053 void DoReleaseTexImage2DCHROMIUM(
1054 GLenum target,
1055 GLint image_id);
1057 void DoTraceEndCHROMIUM(void);
1059 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1061 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1063 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1064 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1066 // Creates a Program for the given program.
1067 Program* CreateProgram(
1068 GLuint client_id, GLuint service_id) {
1069 return program_manager()->CreateProgram(client_id, service_id);
1072 // Gets the program info for the given program. Returns NULL if none exists.
1073 Program* GetProgram(GLuint client_id) {
1074 return program_manager()->GetProgram(client_id);
1077 #if defined(NDEBUG)
1078 void LogClientServiceMapping(
1079 const char* /* function_name */,
1080 GLuint /* client_id */,
1081 GLuint /* service_id */) {
1083 template<typename T>
1084 void LogClientServiceForInfo(
1085 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1087 #else
1088 void LogClientServiceMapping(
1089 const char* function_name, GLuint client_id, GLuint service_id) {
1090 if (service_logging_) {
1091 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1092 << ": client_id = " << client_id
1093 << ", service_id = " << service_id;
1096 template<typename T>
1097 void LogClientServiceForInfo(
1098 T* info, GLuint client_id, const char* function_name) {
1099 if (info) {
1100 LogClientServiceMapping(function_name, client_id, info->service_id());
1103 #endif
1105 // Gets the program info for the given program. If it's not a program
1106 // generates a GL error. Returns NULL if not program.
1107 Program* GetProgramInfoNotShader(
1108 GLuint client_id, const char* function_name) {
1109 Program* program = GetProgram(client_id);
1110 if (!program) {
1111 if (GetShader(client_id)) {
1112 LOCAL_SET_GL_ERROR(
1113 GL_INVALID_OPERATION, function_name, "shader passed for program");
1114 } else {
1115 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1118 LogClientServiceForInfo(program, client_id, function_name);
1119 return program;
1123 // Creates a Shader for the given shader.
1124 Shader* CreateShader(
1125 GLuint client_id,
1126 GLuint service_id,
1127 GLenum shader_type) {
1128 return shader_manager()->CreateShader(
1129 client_id, service_id, shader_type);
1132 // Gets the shader info for the given shader. Returns NULL if none exists.
1133 Shader* GetShader(GLuint client_id) {
1134 return shader_manager()->GetShader(client_id);
1137 // Gets the shader info for the given shader. If it's not a shader generates a
1138 // GL error. Returns NULL if not shader.
1139 Shader* GetShaderInfoNotProgram(
1140 GLuint client_id, const char* function_name) {
1141 Shader* shader = GetShader(client_id);
1142 if (!shader) {
1143 if (GetProgram(client_id)) {
1144 LOCAL_SET_GL_ERROR(
1145 GL_INVALID_OPERATION, function_name, "program passed for shader");
1146 } else {
1147 LOCAL_SET_GL_ERROR(
1148 GL_INVALID_VALUE, function_name, "unknown shader");
1151 LogClientServiceForInfo(shader, client_id, function_name);
1152 return shader;
1155 // Creates a buffer info for the given buffer.
1156 void CreateBuffer(GLuint client_id, GLuint service_id) {
1157 return buffer_manager()->CreateBuffer(client_id, service_id);
1160 // Gets the buffer info for the given buffer.
1161 Buffer* GetBuffer(GLuint client_id) {
1162 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1163 return buffer;
1166 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1167 // on glDeleteBuffers so we can make sure the user does not try to render
1168 // with deleted buffers.
1169 void RemoveBuffer(GLuint client_id);
1171 // Creates a framebuffer info for the given framebuffer.
1172 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1173 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1176 // Gets the framebuffer info for the given framebuffer.
1177 Framebuffer* GetFramebuffer(GLuint client_id) {
1178 return framebuffer_manager()->GetFramebuffer(client_id);
1181 // Removes the framebuffer info for the given framebuffer.
1182 void RemoveFramebuffer(GLuint client_id) {
1183 framebuffer_manager()->RemoveFramebuffer(client_id);
1186 // Creates a renderbuffer info for the given renderbuffer.
1187 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1188 return renderbuffer_manager()->CreateRenderbuffer(
1189 client_id, service_id);
1192 // Gets the renderbuffer info for the given renderbuffer.
1193 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1194 return renderbuffer_manager()->GetRenderbuffer(client_id);
1197 // Removes the renderbuffer info for the given renderbuffer.
1198 void RemoveRenderbuffer(GLuint client_id) {
1199 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1202 // Creates a valuebuffer info for the given valuebuffer.
1203 void CreateValuebuffer(GLuint client_id) {
1204 return valuebuffer_manager()->CreateValuebuffer(client_id);
1207 // Gets the valuebuffer info for a given valuebuffer.
1208 Valuebuffer* GetValuebuffer(GLuint client_id) {
1209 return valuebuffer_manager()->GetValuebuffer(client_id);
1212 // Removes the valuebuffer info for the given valuebuffer.
1213 void RemoveValuebuffer(GLuint client_id) {
1214 valuebuffer_manager()->RemoveValuebuffer(client_id);
1217 // Gets the vertex attrib manager for the given vertex array.
1218 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1219 VertexAttribManager* info =
1220 vertex_array_manager()->GetVertexAttribManager(client_id);
1221 return info;
1224 // Removes the vertex attrib manager for the given vertex array.
1225 void RemoveVertexAttribManager(GLuint client_id) {
1226 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1229 // Creates a vertex attrib manager for the given vertex array.
1230 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1231 GLuint client_id,
1232 GLuint service_id,
1233 bool client_visible) {
1234 return vertex_array_manager()->CreateVertexAttribManager(
1235 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1238 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1239 void DoBindUniformLocationCHROMIUM(
1240 GLuint client_id, GLint location, const char* name);
1242 error::Error GetAttribLocationHelper(
1243 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1244 const std::string& name_str);
1246 error::Error GetUniformLocationHelper(
1247 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1248 const std::string& name_str);
1250 error::Error GetFragDataLocationHelper(
1251 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1252 const std::string& name_str);
1254 // Wrapper for glShaderSource.
1255 void DoShaderSource(
1256 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1258 // Wrapper for glTransformFeedbackVaryings.
1259 void DoTransformFeedbackVaryings(
1260 GLuint client_program_id, GLsizei count, const char* const* varyings,
1261 GLenum buffer_mode);
1263 // Clear any textures used by the current program.
1264 bool ClearUnclearedTextures();
1266 // Clears any uncleared attachments attached to the given frame buffer.
1267 // Returns false if there was a generated GL error.
1268 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1270 // overridden from GLES2Decoder
1271 bool ClearLevel(Texture* texture,
1272 unsigned target,
1273 int level,
1274 unsigned internal_format,
1275 unsigned format,
1276 unsigned type,
1277 int width,
1278 int height,
1279 bool is_texture_immutable) override;
1281 // Restore all GL state that affects clearing.
1282 void RestoreClearState();
1284 // Remembers the state of some capabilities.
1285 // Returns: true if glEnable/glDisable should actually be called.
1286 bool SetCapabilityState(GLenum cap, bool enabled);
1288 // Check that the currently bound framebuffers are valid.
1289 // Generates GL error if not.
1290 bool CheckBoundFramebuffersValid(const char* func_name);
1292 // Check that the currently bound read framebuffer has a color image
1293 // attached. Generates GL error if not.
1294 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1296 // Check that the currently bound read framebuffer's color image
1297 // isn't the target texture of the glCopyTex{Sub}Image2D.
1298 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1300 // Check if a framebuffer meets our requirements.
1301 bool CheckFramebufferValid(
1302 Framebuffer* framebuffer,
1303 GLenum target,
1304 const char* func_name);
1306 // Check if the current valuebuffer exists and is valid. If not generates
1307 // the appropriate GL error. Returns true if the current valuebuffer is in
1308 // a usable state.
1309 bool CheckCurrentValuebuffer(const char* function_name);
1311 // Check if the current valuebuffer exists and is valiud and that the
1312 // value buffer is actually subscribed to the given subscription
1313 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1314 const char* function_name);
1316 // Check if the location can be used for the given subscription target. If not
1317 // generates the appropriate GL error. Returns true if the location is usable
1318 bool CheckSubscriptionTarget(GLint location,
1319 GLenum subscription,
1320 const char* function_name);
1322 // Checks if the current program exists and is valid. If not generates the
1323 // appropriate GL error. Returns true if the current program is in a usable
1324 // state.
1325 bool CheckCurrentProgram(const char* function_name);
1327 // Checks if the current program exists and is valid and that location is not
1328 // -1. If the current program is not valid generates the appropriate GL
1329 // error. Returns true if the current program is in a usable state and
1330 // location is not -1.
1331 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1333 // Checks if the current program samples a texture that is also the color
1334 // image of the current bound framebuffer, i.e., the source and destination
1335 // of the draw operation are the same.
1336 bool CheckDrawingFeedbackLoops();
1338 // Checks if |api_type| is valid for the given uniform
1339 // If the api type is not valid generates the appropriate GL
1340 // error. Returns true if |api_type| is valid for the uniform
1341 bool CheckUniformForApiType(const Program::UniformInfo* info,
1342 const char* function_name,
1343 Program::UniformApiType api_type);
1345 // Gets the type of a uniform for a location in the current program. Sets GL
1346 // errors if the current program is not valid. Returns true if the current
1347 // program is valid and the location exists. Adjusts count so it
1348 // does not overflow the uniform.
1349 bool PrepForSetUniformByLocation(GLint fake_location,
1350 const char* function_name,
1351 Program::UniformApiType api_type,
1352 GLint* real_location,
1353 GLenum* type,
1354 GLsizei* count);
1356 // Gets the service id for any simulated backbuffer fbo.
1357 GLuint GetBackbufferServiceId() const;
1359 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1360 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1362 // Helper for glGetVertexAttrib
1363 void GetVertexAttribHelper(
1364 const VertexAttrib* attrib, GLenum pname, GLint* param);
1366 // Wrapper for glActiveTexture
1367 void DoActiveTexture(GLenum texture_unit);
1369 // Wrapper for glAttachShader
1370 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1372 // Wrapper for glBindBuffer since we need to track the current targets.
1373 void DoBindBuffer(GLenum target, GLuint buffer);
1375 // Wrapper for glBindFramebuffer since we need to track the current targets.
1376 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1378 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1379 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1381 // Wrapper for glBindTexture since we need to track the current targets.
1382 void DoBindTexture(GLenum target, GLuint texture);
1384 // Wrapper for glBindVertexArrayOES
1385 void DoBindVertexArrayOES(GLuint array);
1386 void EmulateVertexArrayState();
1388 // Wrapper for glBlitFramebufferCHROMIUM.
1389 void DoBlitFramebufferCHROMIUM(
1390 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1391 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1392 GLbitfield mask, GLenum filter);
1394 // Wrapper for glBufferSubData.
1395 void DoBufferSubData(
1396 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1398 // Wrapper for glCheckFramebufferStatus
1399 GLenum DoCheckFramebufferStatus(GLenum target);
1401 // Wrapper for glClear
1402 error::Error DoClear(GLbitfield mask);
1404 // Wrappers for various state.
1405 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1406 void DoSampleCoverage(GLclampf value, GLboolean invert);
1408 // Wrapper for glCompileShader.
1409 void DoCompileShader(GLuint shader);
1411 // Wrapper for glDetachShader
1412 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1414 // Wrapper for glDisable
1415 void DoDisable(GLenum cap);
1417 // Wrapper for glDisableVertexAttribArray.
1418 void DoDisableVertexAttribArray(GLuint index);
1420 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1421 // attachments.
1422 void DoDiscardFramebufferEXT(GLenum target,
1423 GLsizei numAttachments,
1424 const GLenum* attachments);
1426 // Wrapper for glEnable
1427 void DoEnable(GLenum cap);
1429 // Wrapper for glEnableVertexAttribArray.
1430 void DoEnableVertexAttribArray(GLuint index);
1432 // Wrapper for glFinish.
1433 void DoFinish();
1435 // Wrapper for glFlush.
1436 void DoFlush();
1438 // Wrapper for glFramebufferRenderbufffer.
1439 void DoFramebufferRenderbuffer(
1440 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1441 GLuint renderbuffer);
1443 // Wrapper for glFramebufferTexture2D.
1444 void DoFramebufferTexture2D(
1445 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1446 GLint level);
1448 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1449 void DoFramebufferTexture2DMultisample(
1450 GLenum target, GLenum attachment, GLenum textarget,
1451 GLuint texture, GLint level, GLsizei samples);
1453 // Common implementation for both DoFramebufferTexture2D wrappers.
1454 void DoFramebufferTexture2DCommon(const char* name,
1455 GLenum target, GLenum attachment, GLenum textarget,
1456 GLuint texture, GLint level, GLsizei samples);
1458 // Wrapper for glFramebufferTextureLayer.
1459 void DoFramebufferTextureLayer(
1460 GLenum target, GLenum attachment, GLuint texture, GLint level,
1461 GLint layer);
1463 // Wrapper for glGenerateMipmap
1464 void DoGenerateMipmap(GLenum target);
1466 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1467 // to account for different pname values defined in different extension
1468 // variants.
1469 GLenum AdjustGetPname(GLenum pname);
1471 // Wrapper for DoGetBooleanv.
1472 void DoGetBooleanv(GLenum pname, GLboolean* params);
1474 // Wrapper for DoGetFloatv.
1475 void DoGetFloatv(GLenum pname, GLfloat* params);
1477 // Wrapper for glGetFramebufferAttachmentParameteriv.
1478 void DoGetFramebufferAttachmentParameteriv(
1479 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1481 // Wrapper for glGetInteger64v.
1482 void DoGetInteger64v(GLenum pname, GLint64* params);
1484 // Wrapper for glGetIntegerv.
1485 void DoGetIntegerv(GLenum pname, GLint* params);
1487 // Gets the max value in a range in a buffer.
1488 GLuint DoGetMaxValueInBufferCHROMIUM(
1489 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1491 // Wrapper for glGetBufferParameteriv.
1492 void DoGetBufferParameteriv(
1493 GLenum target, GLenum pname, GLint* params);
1495 // Wrapper for glGetProgramiv.
1496 void DoGetProgramiv(
1497 GLuint program_id, GLenum pname, GLint* params);
1499 // Wrapper for glRenderbufferParameteriv.
1500 void DoGetRenderbufferParameteriv(
1501 GLenum target, GLenum pname, GLint* params);
1503 // Wrapper for glGetShaderiv
1504 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1506 // Wrappers for glGetTexParameter.
1507 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1508 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1509 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1511 // Wrappers for glGetVertexAttrib.
1512 template <typename T>
1513 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1514 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1515 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1516 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1517 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1519 // Wrappers for glIsXXX functions.
1520 bool DoIsEnabled(GLenum cap);
1521 bool DoIsBuffer(GLuint client_id);
1522 bool DoIsFramebuffer(GLuint client_id);
1523 bool DoIsProgram(GLuint client_id);
1524 bool DoIsRenderbuffer(GLuint client_id);
1525 bool DoIsShader(GLuint client_id);
1526 bool DoIsTexture(GLuint client_id);
1527 bool DoIsVertexArrayOES(GLuint client_id);
1529 // Wrapper for glLinkProgram
1530 void DoLinkProgram(GLuint program);
1532 // Wrapper for glRenderbufferStorage.
1533 void DoRenderbufferStorage(
1534 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1536 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1537 void DoRenderbufferStorageMultisampleCHROMIUM(
1538 GLenum target, GLsizei samples, GLenum internalformat,
1539 GLsizei width, GLsizei height);
1541 // Handler for glRenderbufferStorageMultisampleEXT
1542 // (multisampled_render_to_texture).
1543 void DoRenderbufferStorageMultisampleEXT(
1544 GLenum target, GLsizei samples, GLenum internalformat,
1545 GLsizei width, GLsizei height);
1547 // Common validation for multisample extensions.
1548 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1549 GLenum internalformat,
1550 GLsizei width,
1551 GLsizei height);
1553 // Verifies that the currently bound multisample renderbuffer is valid
1554 // Very slow! Only done on platforms with driver bugs that return invalid
1555 // buffers under memory pressure
1556 bool VerifyMultisampleRenderbufferIntegrity(
1557 GLuint renderbuffer, GLenum format);
1559 // Wrapper for glReleaseShaderCompiler.
1560 void DoReleaseShaderCompiler() { }
1562 // Wrappers for glSamplerParameter*v functions.
1563 void DoSamplerParameterfv(
1564 GLuint sampler, GLenum pname, const GLfloat* params);
1565 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1567 // Wrappers for glTexParameter functions.
1568 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1569 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1570 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1571 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1573 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1574 // spec only these 2 functions can be used to set sampler uniforms.
1575 void DoUniform1i(GLint fake_location, GLint v0);
1576 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1577 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1578 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1579 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1581 // Wrappers for glUniformfv because some drivers don't correctly accept
1582 // bool uniforms.
1583 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1584 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1585 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1586 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1588 void DoUniformMatrix2fv(
1589 GLint fake_location, GLsizei count, GLboolean transpose,
1590 const GLfloat* value);
1591 void DoUniformMatrix3fv(
1592 GLint fake_location, GLsizei count, GLboolean transpose,
1593 const GLfloat* value);
1594 void DoUniformMatrix4fv(
1595 GLint fake_location, GLsizei count, GLboolean transpose,
1596 const GLfloat* value);
1598 template <typename T>
1599 bool SetVertexAttribValue(
1600 const char* function_name, GLuint index, const T* value);
1602 // Wrappers for glVertexAttrib??
1603 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1604 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1605 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1606 void DoVertexAttrib4f(
1607 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1608 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1609 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1610 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1611 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1612 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1613 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1614 void DoVertexAttribI4ui(
1615 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1616 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1618 // Wrapper for glViewport
1619 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1621 // Wrapper for glUseProgram
1622 void DoUseProgram(GLuint program);
1624 // Wrapper for glValidateProgram.
1625 void DoValidateProgram(GLuint program_client_id);
1627 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1628 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1629 void DoPopGroupMarkerEXT(void);
1631 // Gets the number of values that will be returned by glGetXXX. Returns
1632 // false if pname is unknown.
1633 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1635 // Checks if the current program and vertex attributes are valid for drawing.
1636 bool IsDrawValid(
1637 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1638 GLsizei primcount);
1640 // Returns true if successful, simulated will be true if attrib0 was
1641 // simulated.
1642 bool SimulateAttrib0(
1643 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1644 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1646 // If an image is bound to texture, this will call Will/DidUseTexImage
1647 // if needed.
1648 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1649 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1651 // Returns false if textures were replaced.
1652 bool PrepareTexturesForRender();
1653 void RestoreStateForTextures();
1655 // Returns true if GL_FIXED attribs were simulated.
1656 bool SimulateFixedAttribs(
1657 const char* function_name,
1658 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1659 void RestoreStateForSimulatedFixedAttribs();
1661 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1662 // cases (primcount is always 1 for non-instanced).
1663 error::Error DoDrawArrays(
1664 const char* function_name,
1665 bool instanced, GLenum mode, GLint first, GLsizei count,
1666 GLsizei primcount);
1667 error::Error DoDrawElements(
1668 const char* function_name,
1669 bool instanced, GLenum mode, GLsizei count, GLenum type,
1670 int32 offset, GLsizei primcount);
1672 GLenum GetBindTargetForSamplerType(GLenum type) {
1673 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1674 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1675 switch (type) {
1676 case GL_SAMPLER_2D:
1677 return GL_TEXTURE_2D;
1678 case GL_SAMPLER_CUBE:
1679 return GL_TEXTURE_CUBE_MAP;
1680 case GL_SAMPLER_EXTERNAL_OES:
1681 return GL_TEXTURE_EXTERNAL_OES;
1682 case GL_SAMPLER_2D_RECT_ARB:
1683 return GL_TEXTURE_RECTANGLE_ARB;
1686 NOTREACHED();
1687 return 0;
1690 // Gets the framebuffer info for a particular target.
1691 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1692 Framebuffer* framebuffer = NULL;
1693 switch (target) {
1694 case GL_FRAMEBUFFER:
1695 case GL_DRAW_FRAMEBUFFER_EXT:
1696 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1697 break;
1698 case GL_READ_FRAMEBUFFER_EXT:
1699 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1700 break;
1701 default:
1702 NOTREACHED();
1703 break;
1705 return framebuffer;
1708 Renderbuffer* GetRenderbufferInfoForTarget(
1709 GLenum target) {
1710 Renderbuffer* renderbuffer = NULL;
1711 switch (target) {
1712 case GL_RENDERBUFFER:
1713 renderbuffer = state_.bound_renderbuffer.get();
1714 break;
1715 default:
1716 NOTREACHED();
1717 break;
1719 return renderbuffer;
1722 // Validates the program and location for a glGetUniform call and returns
1723 // a SizeResult setup to receive the result. Returns true if glGetUniform
1724 // should be called.
1725 template <class T>
1726 bool GetUniformSetup(GLuint program,
1727 GLint fake_location,
1728 uint32 shm_id,
1729 uint32 shm_offset,
1730 error::Error* error,
1731 GLint* real_location,
1732 GLuint* service_id,
1733 SizedResult<T>** result,
1734 GLenum* result_type,
1735 GLsizei* result_size);
1737 bool WasContextLost() const override;
1738 bool WasContextLostByRobustnessExtension() const override;
1739 void MarkContextLost(error::ContextLostReason reason) override;
1740 bool CheckResetStatus();
1742 #if defined(OS_MACOSX)
1743 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1744 #endif
1746 bool ValidateCompressedTexDimensions(
1747 const char* function_name, GLenum target, GLint level,
1748 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1749 bool ValidateCompressedTexFuncData(
1750 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1751 GLenum format, GLsizei size);
1752 bool ValidateCompressedTexSubDimensions(
1753 const char* function_name,
1754 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1755 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1756 Texture* texture);
1757 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1758 GLenum target,
1759 TextureRef* source_texture_ref,
1760 TextureRef* dest_texture_ref,
1761 GLenum dest_internal_format);
1763 void RenderWarning(const char* filename, int line, const std::string& msg);
1764 void PerformanceWarning(
1765 const char* filename, int line, const std::string& msg);
1767 const FeatureInfo::FeatureFlags& features() const {
1768 return feature_info_->feature_flags();
1771 const FeatureInfo::Workarounds& workarounds() const {
1772 return feature_info_->workarounds();
1775 bool ShouldDeferDraws() {
1776 return !offscreen_target_frame_buffer_.get() &&
1777 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1778 surface_->DeferDraws();
1781 bool ShouldDeferReads() {
1782 return !offscreen_target_frame_buffer_.get() &&
1783 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1784 surface_->DeferDraws();
1787 bool IsRobustnessSupported() {
1788 return has_robustness_extension_ &&
1789 context_->WasAllocatedUsingRobustnessExtension();
1792 error::Error WillAccessBoundFramebufferForDraw() {
1793 if (ShouldDeferDraws())
1794 return error::kDeferCommandUntilLater;
1795 if (!offscreen_target_frame_buffer_.get() &&
1796 !framebuffer_state_.bound_draw_framebuffer.get() &&
1797 !surface_->SetBackbufferAllocation(true))
1798 return error::kLostContext;
1799 return error::kNoError;
1802 error::Error WillAccessBoundFramebufferForRead() {
1803 if (ShouldDeferReads())
1804 return error::kDeferCommandUntilLater;
1805 if (!offscreen_target_frame_buffer_.get() &&
1806 !framebuffer_state_.bound_read_framebuffer.get() &&
1807 !surface_->SetBackbufferAllocation(true))
1808 return error::kLostContext;
1809 return error::kNoError;
1812 // Set remaining commands to process to 0 to force DoCommands to return
1813 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1814 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1816 void ProcessPendingReadPixels();
1817 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1819 // Generate a member function prototype for each command in an automated and
1820 // typesafe way.
1821 #define GLES2_CMD_OP(name) \
1822 Error Handle##name(uint32 immediate_data_size, const void* data);
1824 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1826 #undef GLES2_CMD_OP
1828 // The GL context this decoder renders to on behalf of the client.
1829 scoped_refptr<gfx::GLSurface> surface_;
1830 scoped_refptr<gfx::GLContext> context_;
1832 // The ContextGroup for this decoder uses to track resources.
1833 scoped_refptr<ContextGroup> group_;
1835 DebugMarkerManager debug_marker_manager_;
1836 Logger logger_;
1838 // All the state for this context.
1839 ContextState state_;
1841 // Current width and height of the offscreen frame buffer.
1842 gfx::Size offscreen_size_;
1844 // Util to help with GL.
1845 GLES2Util util_;
1847 // unpack flip y as last set by glPixelStorei
1848 bool unpack_flip_y_;
1850 // unpack (un)premultiply alpha as last set by glPixelStorei
1851 bool unpack_premultiply_alpha_;
1852 bool unpack_unpremultiply_alpha_;
1854 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1855 GLuint attrib_0_buffer_id_;
1857 // The value currently in attrib_0.
1858 Vec4 attrib_0_value_;
1860 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1861 bool attrib_0_buffer_matches_value_;
1863 // The size of attrib 0.
1864 GLsizei attrib_0_size_;
1866 // The buffer used to simulate GL_FIXED attribs.
1867 GLuint fixed_attrib_buffer_id_;
1869 // The size of fiixed attrib buffer.
1870 GLsizei fixed_attrib_buffer_size_;
1872 // The offscreen frame buffer that the client renders to. With EGL, the
1873 // depth and stencil buffers are separate. With regular GL there is a single
1874 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1875 // offscreen_target_stencil_render_buffer_ is unused.
1876 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1877 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1878 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1879 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1880 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1881 GLenum offscreen_target_color_format_;
1882 GLenum offscreen_target_depth_format_;
1883 GLenum offscreen_target_stencil_format_;
1884 GLsizei offscreen_target_samples_;
1885 GLboolean offscreen_target_buffer_preserved_;
1887 // The copy that is saved when SwapBuffers is called.
1888 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1889 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1890 scoped_refptr<TextureRef>
1891 offscreen_saved_color_texture_info_;
1893 // The copy that is used as the destination for multi-sample resolves.
1894 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1895 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1896 GLenum offscreen_saved_color_format_;
1898 scoped_ptr<QueryManager> query_manager_;
1900 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1902 scoped_ptr<ImageManager> image_manager_;
1904 base::Callback<void(gfx::Size, float)> resize_callback_;
1906 WaitSyncPointCallback wait_sync_point_callback_;
1908 ShaderCacheCallback shader_cache_callback_;
1910 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1912 // The format of the back buffer_
1913 GLenum back_buffer_color_format_;
1914 bool back_buffer_has_depth_;
1915 bool back_buffer_has_stencil_;
1917 bool surfaceless_;
1919 // Backbuffer attachments that are currently undefined.
1920 uint32 backbuffer_needs_clear_bits_;
1922 // The current decoder error communicates the decoder error through command
1923 // processing functions that do not return the error value. Should be set only
1924 // if not returning an error.
1925 error::Error current_decoder_error_;
1927 bool use_shader_translator_;
1928 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
1929 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
1931 DisallowedFeatures disallowed_features_;
1933 // Cached from ContextGroup
1934 const Validators* validators_;
1935 scoped_refptr<FeatureInfo> feature_info_;
1937 int frame_number_;
1939 // Number of commands remaining to be processed in DoCommands().
1940 int commands_to_process_;
1942 bool has_robustness_extension_;
1943 error::ContextLostReason context_lost_reason_;
1944 bool context_was_lost_;
1945 bool reset_by_robustness_extension_;
1946 bool supports_post_sub_buffer_;
1948 // These flags are used to override the state of the shared feature_info_
1949 // member. Because the same FeatureInfo instance may be shared among many
1950 // contexts, the assumptions on the availablity of extensions in WebGL
1951 // contexts may be broken. These flags override the shared state to preserve
1952 // WebGL semantics.
1953 bool force_webgl_glsl_validation_;
1954 bool derivatives_explicitly_enabled_;
1955 bool frag_depth_explicitly_enabled_;
1956 bool draw_buffers_explicitly_enabled_;
1957 bool shader_texture_lod_explicitly_enabled_;
1959 bool compile_shader_always_succeeds_;
1961 // An optional behaviour to lose the context and group when OOM.
1962 bool lose_context_when_out_of_memory_;
1964 // Log extra info.
1965 bool service_logging_;
1967 #if defined(OS_MACOSX)
1968 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1969 TextureToIOSurfaceMap texture_to_io_surface_map_;
1970 #endif
1972 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1973 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
1975 // Cached values of the currently assigned viewport dimensions.
1976 GLsizei viewport_max_width_;
1977 GLsizei viewport_max_height_;
1979 // Command buffer stats.
1980 base::TimeDelta total_processing_commands_time_;
1982 // States related to each manager.
1983 DecoderTextureState texture_state_;
1984 DecoderFramebufferState framebuffer_state_;
1986 scoped_ptr<GPUTracer> gpu_tracer_;
1987 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1988 const unsigned char* cb_command_trace_category_;
1989 const unsigned char* gpu_decoder_category_;
1990 int gpu_trace_level_;
1991 bool gpu_trace_commands_;
1992 bool gpu_debug_commands_;
1994 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1996 // Used to validate multisample renderbuffers if needed
1997 GLuint validation_texture_;
1998 GLuint validation_fbo_multisample_;
1999 GLuint validation_fbo_;
2001 bool allow_exit_;
2003 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2004 uint32 immediate_data_size,
2005 const void* data);
2007 // A struct to hold info about each command.
2008 struct CommandInfo {
2009 CmdHandler cmd_handler;
2010 uint8 arg_flags; // How to handle the arguments for this command
2011 uint8 cmd_flags; // How to handle this command
2012 uint16 arg_count; // How many arguments are expected for this command.
2015 // A table of CommandInfo for all the commands.
2016 static const CommandInfo command_info[kNumCommands - kStartPoint];
2018 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2021 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2022 #define GLES2_CMD_OP(name) \
2024 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2025 cmds::name::cmd_flags, \
2026 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2028 , /* NOLINT */
2029 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2030 #undef GLES2_CMD_OP
2033 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2034 const char* function_name, ErrorState* error_state)
2035 : function_name_(function_name),
2036 error_state_(error_state) {
2037 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2040 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2041 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2044 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2045 TextureUnit& info = state->texture_units[0];
2046 GLuint last_id;
2047 scoped_refptr<TextureRef> texture_ref;
2048 switch (target) {
2049 case GL_TEXTURE_2D:
2050 texture_ref = info.bound_texture_2d;
2051 break;
2052 case GL_TEXTURE_CUBE_MAP:
2053 texture_ref = info.bound_texture_cube_map;
2054 break;
2055 case GL_TEXTURE_EXTERNAL_OES:
2056 texture_ref = info.bound_texture_external_oes;
2057 break;
2058 case GL_TEXTURE_RECTANGLE_ARB:
2059 texture_ref = info.bound_texture_rectangle_arb;
2060 break;
2061 default:
2062 NOTREACHED();
2063 break;
2065 if (texture_ref.get()) {
2066 last_id = texture_ref->service_id();
2067 } else {
2068 last_id = 0;
2071 glBindTexture(target, last_id);
2072 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2075 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2076 GLuint id,
2077 GLenum target)
2078 : state_(state),
2079 target_(target) {
2080 ScopedGLErrorSuppressor suppressor(
2081 "ScopedTextureBinder::ctor", state_->GetErrorState());
2083 // TODO(apatrick): Check if there are any other states that need to be reset
2084 // before binding a new texture.
2085 glActiveTexture(GL_TEXTURE0);
2086 glBindTexture(target, id);
2089 ScopedTextureBinder::~ScopedTextureBinder() {
2090 ScopedGLErrorSuppressor suppressor(
2091 "ScopedTextureBinder::dtor", state_->GetErrorState());
2092 RestoreCurrentTextureBindings(state_, target_);
2095 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2096 GLuint id)
2097 : state_(state) {
2098 ScopedGLErrorSuppressor suppressor(
2099 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2100 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2103 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2104 ScopedGLErrorSuppressor suppressor(
2105 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2106 state_->RestoreRenderbufferBindings();
2109 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2110 GLuint id)
2111 : decoder_(decoder) {
2112 ScopedGLErrorSuppressor suppressor(
2113 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2114 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2115 decoder->OnFboChanged();
2118 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2119 ScopedGLErrorSuppressor suppressor(
2120 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2121 decoder_->RestoreCurrentFramebufferBindings();
2124 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2125 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2126 : decoder_(decoder) {
2127 resolve_and_bind_ = (
2128 decoder_->offscreen_target_frame_buffer_.get() &&
2129 decoder_->IsOffscreenBufferMultisampled() &&
2130 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2131 enforce_internal_framebuffer));
2132 if (!resolve_and_bind_)
2133 return;
2135 ScopedGLErrorSuppressor suppressor(
2136 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2137 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2138 decoder_->offscreen_target_frame_buffer_->id());
2139 GLuint targetid;
2140 if (internal) {
2141 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2142 decoder_->offscreen_resolved_frame_buffer_.reset(
2143 new BackFramebuffer(decoder_));
2144 decoder_->offscreen_resolved_frame_buffer_->Create();
2145 decoder_->offscreen_resolved_color_texture_.reset(
2146 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2147 decoder_->offscreen_resolved_color_texture_->Create();
2149 DCHECK(decoder_->offscreen_saved_color_format_);
2150 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2151 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2152 false);
2153 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2154 decoder_->offscreen_resolved_color_texture_.get());
2155 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2156 GL_FRAMEBUFFER_COMPLETE) {
2157 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2158 << "because offscreen resolved FBO was incomplete.";
2159 return;
2162 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2163 } else {
2164 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2166 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2167 const int width = decoder_->offscreen_size_.width();
2168 const int height = decoder_->offscreen_size_.height();
2169 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2170 decoder->BlitFramebufferHelper(0,
2172 width,
2173 height,
2176 width,
2177 height,
2178 GL_COLOR_BUFFER_BIT,
2179 GL_NEAREST);
2180 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2183 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2184 if (!resolve_and_bind_)
2185 return;
2187 ScopedGLErrorSuppressor suppressor(
2188 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2189 decoder_->RestoreCurrentFramebufferBindings();
2190 if (decoder_->state_.enable_flags.scissor_test) {
2191 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2195 BackTexture::BackTexture(
2196 MemoryTracker* memory_tracker,
2197 ContextState* state)
2198 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2199 state_(state),
2200 bytes_allocated_(0),
2201 id_(0) {
2204 BackTexture::~BackTexture() {
2205 // This does not destroy the render texture because that would require that
2206 // the associated GL context was current. Just check that it was explicitly
2207 // destroyed.
2208 DCHECK_EQ(id_, 0u);
2211 void BackTexture::Create() {
2212 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2213 state_->GetErrorState());
2214 Destroy();
2215 glGenTextures(1, &id_);
2216 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2222 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2223 // never called on an offscreen context, no data will ever be uploaded to the
2224 // saved offscreen color texture (it is deferred until to when SwapBuffers
2225 // is called). My idea is that some nvidia drivers might have a bug where
2226 // deleting a texture that has never been populated might cause a
2227 // crash.
2228 glTexImage2D(
2229 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2231 bytes_allocated_ = 16u * 16u * 4u;
2232 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2235 bool BackTexture::AllocateStorage(
2236 const gfx::Size& size, GLenum format, bool zero) {
2237 DCHECK_NE(id_, 0u);
2238 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2239 state_->GetErrorState());
2240 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2241 uint32 image_size = 0;
2242 GLES2Util::ComputeImageDataSizes(
2243 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2244 NULL, NULL);
2246 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2247 return false;
2250 scoped_ptr<char[]> zero_data;
2251 if (zero) {
2252 zero_data.reset(new char[image_size]);
2253 memset(zero_data.get(), 0, image_size);
2256 glTexImage2D(GL_TEXTURE_2D,
2257 0, // mip level
2258 format,
2259 size.width(),
2260 size.height(),
2261 0, // border
2262 format,
2263 GL_UNSIGNED_BYTE,
2264 zero_data.get());
2266 size_ = size;
2268 bool success = glGetError() == GL_NO_ERROR;
2269 if (success) {
2270 memory_tracker_.TrackMemFree(bytes_allocated_);
2271 bytes_allocated_ = image_size;
2272 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2274 return success;
2277 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2278 DCHECK_NE(id_, 0u);
2279 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2280 state_->GetErrorState());
2281 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2282 glCopyTexImage2D(GL_TEXTURE_2D,
2283 0, // level
2284 format,
2285 0, 0,
2286 size.width(),
2287 size.height(),
2288 0); // border
2291 void BackTexture::Destroy() {
2292 if (id_ != 0) {
2293 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2294 state_->GetErrorState());
2295 glDeleteTextures(1, &id_);
2296 id_ = 0;
2298 memory_tracker_.TrackMemFree(bytes_allocated_);
2299 bytes_allocated_ = 0;
2302 void BackTexture::Invalidate() {
2303 id_ = 0;
2306 BackRenderbuffer::BackRenderbuffer(
2307 RenderbufferManager* renderbuffer_manager,
2308 MemoryTracker* memory_tracker,
2309 ContextState* state)
2310 : renderbuffer_manager_(renderbuffer_manager),
2311 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2312 state_(state),
2313 bytes_allocated_(0),
2314 id_(0) {
2317 BackRenderbuffer::~BackRenderbuffer() {
2318 // This does not destroy the render buffer because that would require that
2319 // the associated GL context was current. Just check that it was explicitly
2320 // destroyed.
2321 DCHECK_EQ(id_, 0u);
2324 void BackRenderbuffer::Create() {
2325 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2326 state_->GetErrorState());
2327 Destroy();
2328 glGenRenderbuffersEXT(1, &id_);
2331 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2332 const gfx::Size& size,
2333 GLenum format,
2334 GLsizei samples) {
2335 ScopedGLErrorSuppressor suppressor(
2336 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2337 ScopedRenderBufferBinder binder(state_, id_);
2339 uint32 estimated_size = 0;
2340 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2341 size.width(), size.height(), samples, format, &estimated_size)) {
2342 return false;
2345 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2346 return false;
2349 if (samples <= 1) {
2350 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2351 format,
2352 size.width(),
2353 size.height());
2354 } else {
2355 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2356 GL_RENDERBUFFER,
2357 samples,
2358 format,
2359 size.width(),
2360 size.height());
2362 bool success = glGetError() == GL_NO_ERROR;
2363 if (success) {
2364 // Mark the previously allocated bytes as free.
2365 memory_tracker_.TrackMemFree(bytes_allocated_);
2366 bytes_allocated_ = estimated_size;
2367 // Track the newly allocated bytes.
2368 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2370 return success;
2373 void BackRenderbuffer::Destroy() {
2374 if (id_ != 0) {
2375 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2376 state_->GetErrorState());
2377 glDeleteRenderbuffersEXT(1, &id_);
2378 id_ = 0;
2380 memory_tracker_.TrackMemFree(bytes_allocated_);
2381 bytes_allocated_ = 0;
2384 void BackRenderbuffer::Invalidate() {
2385 id_ = 0;
2388 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2389 : decoder_(decoder),
2390 id_(0) {
2393 BackFramebuffer::~BackFramebuffer() {
2394 // This does not destroy the frame buffer because that would require that
2395 // the associated GL context was current. Just check that it was explicitly
2396 // destroyed.
2397 DCHECK_EQ(id_, 0u);
2400 void BackFramebuffer::Create() {
2401 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2402 decoder_->GetErrorState());
2403 Destroy();
2404 glGenFramebuffersEXT(1, &id_);
2407 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2408 DCHECK_NE(id_, 0u);
2409 ScopedGLErrorSuppressor suppressor(
2410 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2411 ScopedFrameBufferBinder binder(decoder_, id_);
2412 GLuint attach_id = texture ? texture->id() : 0;
2413 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2414 GL_COLOR_ATTACHMENT0,
2415 GL_TEXTURE_2D,
2416 attach_id,
2420 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2421 BackRenderbuffer* render_buffer) {
2422 DCHECK_NE(id_, 0u);
2423 ScopedGLErrorSuppressor suppressor(
2424 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2425 ScopedFrameBufferBinder binder(decoder_, id_);
2426 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2427 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2428 target,
2429 GL_RENDERBUFFER,
2430 attach_id);
2433 void BackFramebuffer::Destroy() {
2434 if (id_ != 0) {
2435 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2436 decoder_->GetErrorState());
2437 glDeleteFramebuffersEXT(1, &id_);
2438 id_ = 0;
2442 void BackFramebuffer::Invalidate() {
2443 id_ = 0;
2446 GLenum BackFramebuffer::CheckStatus() {
2447 DCHECK_NE(id_, 0u);
2448 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2449 decoder_->GetErrorState());
2450 ScopedFrameBufferBinder binder(decoder_, id_);
2451 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2454 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2455 return new GLES2DecoderImpl(group);
2458 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2459 : GLES2Decoder(),
2460 group_(group),
2461 logger_(&debug_marker_manager_),
2462 state_(group_->feature_info(), this, &logger_),
2463 unpack_flip_y_(false),
2464 unpack_premultiply_alpha_(false),
2465 unpack_unpremultiply_alpha_(false),
2466 attrib_0_buffer_id_(0),
2467 attrib_0_buffer_matches_value_(true),
2468 attrib_0_size_(0),
2469 fixed_attrib_buffer_id_(0),
2470 fixed_attrib_buffer_size_(0),
2471 offscreen_target_color_format_(0),
2472 offscreen_target_depth_format_(0),
2473 offscreen_target_stencil_format_(0),
2474 offscreen_target_samples_(0),
2475 offscreen_target_buffer_preserved_(true),
2476 offscreen_saved_color_format_(0),
2477 back_buffer_color_format_(0),
2478 back_buffer_has_depth_(false),
2479 back_buffer_has_stencil_(false),
2480 surfaceless_(false),
2481 backbuffer_needs_clear_bits_(0),
2482 current_decoder_error_(error::kNoError),
2483 use_shader_translator_(true),
2484 validators_(group_->feature_info()->validators()),
2485 feature_info_(group_->feature_info()),
2486 frame_number_(0),
2487 has_robustness_extension_(false),
2488 context_lost_reason_(error::kUnknown),
2489 context_was_lost_(false),
2490 reset_by_robustness_extension_(false),
2491 supports_post_sub_buffer_(false),
2492 force_webgl_glsl_validation_(false),
2493 derivatives_explicitly_enabled_(false),
2494 frag_depth_explicitly_enabled_(false),
2495 draw_buffers_explicitly_enabled_(false),
2496 shader_texture_lod_explicitly_enabled_(false),
2497 compile_shader_always_succeeds_(false),
2498 lose_context_when_out_of_memory_(false),
2499 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2500 switches::kEnableGPUServiceLoggingGPU)),
2501 viewport_max_width_(0),
2502 viewport_max_height_(0),
2503 texture_state_(group_->feature_info()
2504 ->workarounds()
2505 .texsubimage_faster_than_teximage),
2506 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2507 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2508 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2509 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2510 gpu_trace_level_(2),
2511 gpu_trace_commands_(false),
2512 gpu_debug_commands_(false),
2513 validation_texture_(0),
2514 validation_fbo_multisample_(0),
2515 validation_fbo_(0),
2516 allow_exit_(false) {
2517 DCHECK(group);
2519 // The shader translator is used for WebGL even when running on EGL
2520 // because additional restrictions are needed (like only enabling
2521 // GL_OES_standard_derivatives on demand). It is used for the unit
2522 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2523 // the empty string to CompileShader and this is not a valid shader.
2524 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2525 base::CommandLine::ForCurrentProcess()->HasSwitch(
2526 switches::kDisableGLSLTranslator)) {
2527 use_shader_translator_ = false;
2531 GLES2DecoderImpl::~GLES2DecoderImpl() {
2534 bool GLES2DecoderImpl::Initialize(
2535 const scoped_refptr<gfx::GLSurface>& surface,
2536 const scoped_refptr<gfx::GLContext>& context,
2537 bool offscreen,
2538 const gfx::Size& offscreen_size,
2539 const DisallowedFeatures& disallowed_features,
2540 const std::vector<int32>& attribs) {
2541 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2542 DCHECK(context->IsCurrent(surface.get()));
2543 DCHECK(!context_.get());
2544 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2546 ContextCreationAttribHelper attrib_parser;
2547 if (!attrib_parser.Parse(attribs))
2548 return false;
2550 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2552 set_initialized();
2553 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2555 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2556 switches::kEnableGPUDebugging)) {
2557 set_debug(true);
2560 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2561 switches::kEnableGPUCommandLogging)) {
2562 set_log_commands(true);
2565 compile_shader_always_succeeds_ =
2566 base::CommandLine::ForCurrentProcess()->HasSwitch(
2567 switches::kCompileShaderAlwaysSucceeds);
2569 // Take ownership of the context and surface. The surface can be replaced with
2570 // SetSurface.
2571 context_ = context;
2572 surface_ = surface;
2574 // Create GPU Tracer for timing values.
2575 gpu_tracer_.reset(new GPUTracer(this));
2577 // Save the loseContextWhenOutOfMemory context creation attribute.
2578 lose_context_when_out_of_memory_ =
2579 attrib_parser.lose_context_when_out_of_memory;
2581 // If the failIfMajorPerformanceCaveat context creation attribute was true
2582 // and we are using a software renderer, fail.
2583 if (attrib_parser.fail_if_major_perf_caveat &&
2584 feature_info_->feature_flags().is_swiftshader) {
2585 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2586 Destroy(true);
2587 return false;
2590 if (!group_->Initialize(this, disallowed_features)) {
2591 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2592 << "failed to initialize.";
2593 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2594 Destroy(true);
2595 return false;
2597 CHECK_GL_ERROR();
2599 if (attrib_parser.es3_context_required &&
2600 feature_info_->IsES3Capable()) {
2601 feature_info_->EnableES3Validators();
2602 set_unsafe_es3_apis_enabled(true);
2605 disallowed_features_ = disallowed_features;
2607 state_.attrib_values.resize(group_->max_vertex_attribs());
2608 vertex_array_manager_.reset(new VertexArrayManager());
2610 GLuint default_vertex_attrib_service_id = 0;
2611 if (features().native_vertex_array_object) {
2612 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2613 glBindVertexArrayOES(default_vertex_attrib_service_id);
2616 state_.default_vertex_attrib_manager =
2617 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2619 state_.default_vertex_attrib_manager->Initialize(
2620 group_->max_vertex_attribs(),
2621 feature_info_->workarounds().init_vertex_attributes);
2623 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2624 DoBindVertexArrayOES(0);
2626 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2628 image_manager_.reset(new ImageManager);
2630 util_.set_num_compressed_texture_formats(
2631 validators_->compressed_texture_format.GetValues().size());
2633 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2634 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2635 // OpenGL ES 2.0 does not have this issue.
2636 glEnableVertexAttribArray(0);
2638 glGenBuffersARB(1, &attrib_0_buffer_id_);
2639 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2640 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2641 glBindBuffer(GL_ARRAY_BUFFER, 0);
2642 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2644 state_.texture_units.resize(group_->max_texture_units());
2645 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2646 glActiveTexture(GL_TEXTURE0 + tt);
2647 // We want the last bind to be 2D.
2648 TextureRef* ref;
2649 if (features().oes_egl_image_external) {
2650 ref = texture_manager()->GetDefaultTextureInfo(
2651 GL_TEXTURE_EXTERNAL_OES);
2652 state_.texture_units[tt].bound_texture_external_oes = ref;
2653 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2655 if (features().arb_texture_rectangle) {
2656 ref = texture_manager()->GetDefaultTextureInfo(
2657 GL_TEXTURE_RECTANGLE_ARB);
2658 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2659 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2661 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2662 state_.texture_units[tt].bound_texture_cube_map = ref;
2663 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2664 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2665 state_.texture_units[tt].bound_texture_2d = ref;
2666 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2668 glActiveTexture(GL_TEXTURE0);
2669 CHECK_GL_ERROR();
2671 // cache ALPHA_BITS result for re-use with clear behaviour
2672 GLint alpha_bits = 0;
2674 if (offscreen) {
2675 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2676 features().chromium_framebuffer_multisample) {
2677 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2678 // max_sample_count must be initialized to a sane value. If
2679 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2680 GLint max_sample_count = 1;
2681 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2682 offscreen_target_samples_ = std::min(attrib_parser.samples,
2683 max_sample_count);
2684 } else {
2685 offscreen_target_samples_ = 1;
2687 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2689 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2690 const bool rgb8_supported =
2691 context_->HasExtension("GL_OES_rgb8_rgba8");
2692 // The only available default render buffer formats in GLES2 have very
2693 // little precision. Don't enable multisampling unless 8-bit render
2694 // buffer formats are available--instead fall back to 8-bit textures.
2695 if (rgb8_supported && offscreen_target_samples_ > 1) {
2696 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2697 GL_RGBA8 : GL_RGB8;
2698 } else {
2699 offscreen_target_samples_ = 1;
2700 offscreen_target_color_format_ =
2701 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2702 ? GL_RGBA
2703 : GL_RGB;
2706 // ANGLE only supports packed depth/stencil formats, so use it if it is
2707 // available.
2708 const bool depth24_stencil8_supported =
2709 feature_info_->feature_flags().packed_depth24_stencil8;
2710 VLOG(1) << "GL_OES_packed_depth_stencil "
2711 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2712 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2713 depth24_stencil8_supported) {
2714 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2715 offscreen_target_stencil_format_ = 0;
2716 } else {
2717 // It may be the case that this depth/stencil combination is not
2718 // supported, but this will be checked later by CheckFramebufferStatus.
2719 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2720 GL_DEPTH_COMPONENT16 : 0;
2721 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2722 GL_STENCIL_INDEX8 : 0;
2724 } else {
2725 offscreen_target_color_format_ =
2726 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2727 ? GL_RGBA
2728 : GL_RGB;
2730 // If depth is requested at all, use the packed depth stencil format if
2731 // it's available, as some desktop GL drivers don't support any non-packed
2732 // formats for depth attachments.
2733 const bool depth24_stencil8_supported =
2734 feature_info_->feature_flags().packed_depth24_stencil8;
2735 VLOG(1) << "GL_EXT_packed_depth_stencil "
2736 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2738 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2739 depth24_stencil8_supported) {
2740 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2741 offscreen_target_stencil_format_ = 0;
2742 } else {
2743 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2744 GL_DEPTH_COMPONENT : 0;
2745 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2746 GL_STENCIL_INDEX : 0;
2750 offscreen_saved_color_format_ =
2751 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2752 ? GL_RGBA
2753 : GL_RGB;
2755 // Create the target frame buffer. This is the one that the client renders
2756 // directly to.
2757 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2758 offscreen_target_frame_buffer_->Create();
2759 // Due to GLES2 format limitations, either the color texture (for
2760 // non-multisampling) or the color render buffer (for multisampling) will be
2761 // attached to the offscreen frame buffer. The render buffer has more
2762 // limited formats available to it, but the texture can't do multisampling.
2763 if (IsOffscreenBufferMultisampled()) {
2764 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2765 renderbuffer_manager(), memory_tracker(), &state_));
2766 offscreen_target_color_render_buffer_->Create();
2767 } else {
2768 offscreen_target_color_texture_.reset(new BackTexture(
2769 memory_tracker(), &state_));
2770 offscreen_target_color_texture_->Create();
2772 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2773 renderbuffer_manager(), memory_tracker(), &state_));
2774 offscreen_target_depth_render_buffer_->Create();
2775 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2776 renderbuffer_manager(), memory_tracker(), &state_));
2777 offscreen_target_stencil_render_buffer_->Create();
2779 // Create the saved offscreen texture. The target frame buffer is copied
2780 // here when SwapBuffers is called.
2781 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2782 offscreen_saved_frame_buffer_->Create();
2784 offscreen_saved_color_texture_.reset(new BackTexture(
2785 memory_tracker(), &state_));
2786 offscreen_saved_color_texture_->Create();
2788 // Allocate the render buffers at their initial size and check the status
2789 // of the frame buffers is okay.
2790 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2791 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2792 Destroy(true);
2793 return false;
2796 state_.viewport_width = offscreen_size.width();
2797 state_.viewport_height = offscreen_size.height();
2799 // Allocate the offscreen saved color texture.
2800 DCHECK(offscreen_saved_color_format_);
2801 offscreen_saved_color_texture_->AllocateStorage(
2802 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2804 offscreen_saved_frame_buffer_->AttachRenderTexture(
2805 offscreen_saved_color_texture_.get());
2806 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2807 GL_FRAMEBUFFER_COMPLETE) {
2808 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2809 Destroy(true);
2810 return false;
2813 // Bind to the new default frame buffer (the offscreen target frame buffer).
2814 // This should now be associated with ID zero.
2815 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2816 } else {
2817 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2818 // These are NOT if the back buffer has these proprorties. They are
2819 // if we want the command buffer to enforce them regardless of what
2820 // the real backbuffer is assuming the real back buffer gives us more than
2821 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2822 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2823 // can't do anything about that.
2825 if (!surfaceless_) {
2826 GLint depth_bits = 0;
2827 GLint stencil_bits = 0;
2829 bool default_fb = (GetBackbufferServiceId() == 0);
2831 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2832 glGetFramebufferAttachmentParameterivEXT(
2833 GL_FRAMEBUFFER,
2834 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2835 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2836 glGetFramebufferAttachmentParameterivEXT(
2837 GL_FRAMEBUFFER,
2838 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2839 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2840 glGetFramebufferAttachmentParameterivEXT(
2841 GL_FRAMEBUFFER,
2842 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2843 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2844 } else {
2845 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2846 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2847 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2850 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2851 // the user requested RGB then RGB. If the user did not specify a
2852 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2853 back_buffer_color_format_ =
2854 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2855 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2856 back_buffer_has_stencil_ =
2857 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2860 state_.viewport_width = surface->GetSize().width();
2861 state_.viewport_height = surface->GetSize().height();
2864 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2865 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2866 // isn't well documented; it was discovered in the Khronos OpenGL ES
2867 // mailing list archives. It also implicitly enables the desktop GL
2868 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2869 // variable in fragment shaders.
2870 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2871 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2872 glEnable(GL_POINT_SPRITE);
2875 has_robustness_extension_ =
2876 context->HasExtension("GL_ARB_robustness") ||
2877 context->HasExtension("GL_KHR_robustness") ||
2878 context->HasExtension("GL_EXT_robustness");
2880 if (!InitializeShaderTranslator()) {
2881 return false;
2884 GLint viewport_params[4] = { 0 };
2885 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2886 viewport_max_width_ = viewport_params[0];
2887 viewport_max_height_ = viewport_params[1];
2889 state_.scissor_width = state_.viewport_width;
2890 state_.scissor_height = state_.viewport_height;
2892 // Set all the default state because some GL drivers get it wrong.
2893 state_.InitCapabilities(NULL);
2894 state_.InitState(NULL);
2895 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2897 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2898 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2899 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2900 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2901 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2903 bool call_gl_clear = !surfaceless_;
2904 #if defined(OS_ANDROID)
2905 // Temporary workaround for Android WebView because this clear ignores the
2906 // clip and corrupts that external UI of the App. Not calling glClear is ok
2907 // because the system already clears the buffer before each draw. Proper
2908 // fix might be setting the scissor clip properly before initialize. See
2909 // crbug.com/259023 for details.
2910 call_gl_clear = surface_->GetHandle();
2911 #endif
2912 if (call_gl_clear) {
2913 // On configs where we report no alpha, if the underlying surface has
2914 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2915 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
2916 if (clear_alpha) {
2917 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2920 // Clear the backbuffer.
2921 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2923 // Restore alpha clear value if we changed it.
2924 if (clear_alpha) {
2925 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2929 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2930 if (feature_info_->workarounds()
2931 .disable_post_sub_buffers_for_onscreen_surfaces &&
2932 !surface->IsOffscreen())
2933 supports_post_sub_buffer_ = false;
2935 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2936 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2939 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2940 context_->SetUnbindFboOnMakeCurrent();
2943 // Only compositor contexts are known to use only the subset of GL
2944 // that can be safely migrated between the iGPU and the dGPU. Mark
2945 // those contexts as safe to forcibly transition between the GPUs.
2946 // http://crbug.com/180876, http://crbug.com/227228
2947 if (!offscreen)
2948 context_->SetSafeToForceGpuSwitch();
2950 async_pixel_transfer_manager_.reset(
2951 AsyncPixelTransferManager::Create(context.get()));
2952 async_pixel_transfer_manager_->Initialize(texture_manager());
2954 if (workarounds().gl_clear_broken) {
2955 DCHECK(!clear_framebuffer_blit_.get());
2956 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2957 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
2958 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
2959 return false;
2962 framebuffer_manager()->AddObserver(this);
2964 return true;
2967 Capabilities GLES2DecoderImpl::GetCapabilities() {
2968 DCHECK(initialized());
2969 Capabilities caps;
2970 caps.VisitPrecisions([](GLenum shader, GLenum type,
2971 Capabilities::ShaderPrecision* shader_precision) {
2972 GLint range[2] = {0, 0};
2973 GLint precision = 0;
2974 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
2975 shader_precision->min_range = range[0];
2976 shader_precision->max_range = range[1];
2977 shader_precision->precision = precision;
2979 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
2980 &caps.max_combined_texture_image_units);
2981 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
2982 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
2983 &caps.max_fragment_uniform_vectors);
2984 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
2985 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
2986 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
2987 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
2988 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
2989 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
2990 &caps.max_vertex_texture_image_units);
2991 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
2992 &caps.max_vertex_uniform_vectors);
2993 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
2994 &caps.num_compressed_texture_formats);
2995 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
2996 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
2997 &caps.bind_generates_resource_chromium);
2998 if (unsafe_es3_apis_enabled()) {
2999 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3000 // but for now we clamp them to 32-bit max.
3001 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
3002 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
3003 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3004 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3005 &caps.max_combined_fragment_uniform_components);
3006 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3007 &caps.max_combined_uniform_blocks);
3008 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3009 &caps.max_combined_vertex_uniform_components);
3010 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3011 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3012 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3013 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3014 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3015 &caps.max_fragment_input_components);
3016 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3017 &caps.max_fragment_uniform_blocks);
3018 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3019 &caps.max_fragment_uniform_components);
3020 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3021 &caps.max_program_texel_offset);
3022 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3023 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3024 // returned.
3025 if (caps.max_server_wait_timeout < 0)
3026 caps.max_server_wait_timeout = 0;
3027 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3028 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3029 &caps.max_transform_feedback_interleaved_components);
3030 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3031 &caps.max_transform_feedback_separate_attribs);
3032 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3033 &caps.max_transform_feedback_separate_components);
3034 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3035 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3036 &caps.max_uniform_buffer_bindings);
3037 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3038 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3039 &caps.max_vertex_output_components);
3040 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3041 &caps.max_vertex_uniform_blocks);
3042 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3043 &caps.max_vertex_uniform_components);
3044 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3045 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3046 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3047 &caps.num_program_binary_formats);
3048 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3049 &caps.uniform_buffer_offset_alignment);
3050 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3051 caps.major_version = 3;
3052 caps.minor_version = 0;
3054 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3055 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3056 unsafe_es3_apis_enabled()) {
3057 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3060 caps.egl_image_external =
3061 feature_info_->feature_flags().oes_egl_image_external;
3062 caps.texture_format_atc =
3063 feature_info_->feature_flags().ext_texture_format_atc;
3064 caps.texture_format_bgra8888 =
3065 feature_info_->feature_flags().ext_texture_format_bgra8888;
3066 caps.texture_format_dxt1 =
3067 feature_info_->feature_flags().ext_texture_format_dxt1;
3068 caps.texture_format_dxt5 =
3069 feature_info_->feature_flags().ext_texture_format_dxt5;
3070 caps.texture_format_etc1 =
3071 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3072 caps.texture_format_etc1_npot =
3073 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3074 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3075 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3076 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3077 caps.discard_framebuffer =
3078 feature_info_->feature_flags().ext_discard_framebuffer;
3079 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3081 #if defined(OS_MACOSX)
3082 // This is unconditionally true on mac, no need to test for it at runtime.
3083 caps.iosurface = true;
3084 #endif
3086 caps.post_sub_buffer = supports_post_sub_buffer_;
3087 caps.image = true;
3089 caps.blend_equation_advanced =
3090 feature_info_->feature_flags().blend_equation_advanced;
3091 caps.blend_equation_advanced_coherent =
3092 feature_info_->feature_flags().blend_equation_advanced_coherent;
3093 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3094 return caps;
3097 void GLES2DecoderImpl::UpdateCapabilities() {
3098 util_.set_num_compressed_texture_formats(
3099 validators_->compressed_texture_format.GetValues().size());
3100 util_.set_num_shader_binary_formats(
3101 validators_->shader_binary_format.GetValues().size());
3104 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3105 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3107 if (!use_shader_translator_) {
3108 return true;
3110 ShBuiltInResources resources;
3111 ShInitBuiltInResources(&resources);
3112 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3113 resources.MaxVertexUniformVectors =
3114 group_->max_vertex_uniform_vectors();
3115 resources.MaxVaryingVectors = group_->max_varying_vectors();
3116 resources.MaxVertexTextureImageUnits =
3117 group_->max_vertex_texture_image_units();
3118 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3119 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3120 resources.MaxFragmentUniformVectors =
3121 group_->max_fragment_uniform_vectors();
3122 resources.MaxDrawBuffers = group_->max_draw_buffers();
3123 resources.MaxExpressionComplexity = 256;
3124 resources.MaxCallStackDepth = 256;
3126 GLint range[2] = { 0, 0 };
3127 GLint precision = 0;
3128 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3129 range, &precision);
3130 resources.FragmentPrecisionHigh =
3131 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3133 if (force_webgl_glsl_validation_) {
3134 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3135 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3136 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3137 if (!draw_buffers_explicitly_enabled_)
3138 resources.MaxDrawBuffers = 1;
3139 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3140 resources.NV_draw_buffers =
3141 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3142 } else {
3143 resources.OES_standard_derivatives =
3144 features().oes_standard_derivatives ? 1 : 0;
3145 resources.ARB_texture_rectangle =
3146 features().arb_texture_rectangle ? 1 : 0;
3147 resources.OES_EGL_image_external =
3148 features().oes_egl_image_external ? 1 : 0;
3149 resources.EXT_draw_buffers =
3150 features().ext_draw_buffers ? 1 : 0;
3151 resources.EXT_frag_depth =
3152 features().ext_frag_depth ? 1 : 0;
3153 resources.EXT_shader_texture_lod =
3154 features().ext_shader_texture_lod ? 1 : 0;
3155 resources.NV_draw_buffers =
3156 features().nv_draw_buffers ? 1 : 0;
3159 ShShaderSpec shader_spec;
3160 if (force_webgl_glsl_validation_) {
3161 shader_spec = unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3162 } else {
3163 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3166 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3167 features().enable_shader_name_hashing)
3168 resources.HashFunction = &CityHash64;
3169 else
3170 resources.HashFunction = NULL;
3171 ShaderTranslatorInterface::GlslImplementationType implementation_type =
3172 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
3173 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
3174 int driver_bug_workarounds = 0;
3175 if (workarounds().needs_glsl_built_in_function_emulation)
3176 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3177 if (workarounds().init_gl_position_in_vertex_shader)
3178 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3179 if (workarounds().unfold_short_circuit_as_ternary_operation)
3180 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3181 if (workarounds().init_varyings_without_static_use)
3182 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3183 if (workarounds().unroll_for_loop_with_sampler_array_index)
3184 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3185 if (workarounds().scalarize_vec_and_mat_constructor_args)
3186 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3187 if (workarounds().regenerate_struct_names)
3188 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3189 if (workarounds().remove_pow_with_constant_exponent)
3190 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3192 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3193 switches::kEmulateShaderPrecision))
3194 resources.WEBGL_debug_shader_precision = true;
3196 vertex_translator_ = shader_translator_cache()->GetTranslator(
3197 GL_VERTEX_SHADER,
3198 shader_spec,
3199 &resources,
3200 implementation_type,
3201 static_cast<ShCompileOptions>(driver_bug_workarounds));
3202 if (!vertex_translator_.get()) {
3203 LOG(ERROR) << "Could not initialize vertex shader translator.";
3204 Destroy(true);
3205 return false;
3208 fragment_translator_ = shader_translator_cache()->GetTranslator(
3209 GL_FRAGMENT_SHADER,
3210 shader_spec,
3211 &resources,
3212 implementation_type,
3213 static_cast<ShCompileOptions>(driver_bug_workarounds));
3214 if (!fragment_translator_.get()) {
3215 LOG(ERROR) << "Could not initialize fragment shader translator.";
3216 Destroy(true);
3217 return false;
3219 return true;
3222 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3223 for (GLsizei ii = 0; ii < n; ++ii) {
3224 if (GetBuffer(client_ids[ii])) {
3225 return false;
3228 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3229 glGenBuffersARB(n, service_ids.get());
3230 for (GLsizei ii = 0; ii < n; ++ii) {
3231 CreateBuffer(client_ids[ii], service_ids[ii]);
3233 return true;
3236 bool GLES2DecoderImpl::GenFramebuffersHelper(
3237 GLsizei n, const GLuint* client_ids) {
3238 for (GLsizei ii = 0; ii < n; ++ii) {
3239 if (GetFramebuffer(client_ids[ii])) {
3240 return false;
3243 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3244 glGenFramebuffersEXT(n, service_ids.get());
3245 for (GLsizei ii = 0; ii < n; ++ii) {
3246 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3248 return true;
3251 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3252 GLsizei n, const GLuint* client_ids) {
3253 for (GLsizei ii = 0; ii < n; ++ii) {
3254 if (GetRenderbuffer(client_ids[ii])) {
3255 return false;
3258 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3259 glGenRenderbuffersEXT(n, service_ids.get());
3260 for (GLsizei ii = 0; ii < n; ++ii) {
3261 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3263 return true;
3266 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3267 const GLuint* client_ids) {
3268 for (GLsizei ii = 0; ii < n; ++ii) {
3269 if (GetValuebuffer(client_ids[ii])) {
3270 return false;
3273 for (GLsizei ii = 0; ii < n; ++ii) {
3274 CreateValuebuffer(client_ids[ii]);
3276 return true;
3279 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3280 for (GLsizei ii = 0; ii < n; ++ii) {
3281 if (GetTexture(client_ids[ii])) {
3282 return false;
3285 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3286 glGenTextures(n, service_ids.get());
3287 for (GLsizei ii = 0; ii < n; ++ii) {
3288 CreateTexture(client_ids[ii], service_ids[ii]);
3290 return true;
3293 void GLES2DecoderImpl::DeleteBuffersHelper(
3294 GLsizei n, const GLuint* client_ids) {
3295 for (GLsizei ii = 0; ii < n; ++ii) {
3296 Buffer* buffer = GetBuffer(client_ids[ii]);
3297 if (buffer && !buffer->IsDeleted()) {
3298 buffer->RemoveMappedRange();
3299 state_.RemoveBoundBuffer(buffer);
3300 RemoveBuffer(client_ids[ii]);
3305 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3306 GLsizei n, const GLuint* client_ids) {
3307 bool supports_separate_framebuffer_binds =
3308 features().chromium_framebuffer_multisample;
3310 for (GLsizei ii = 0; ii < n; ++ii) {
3311 Framebuffer* framebuffer =
3312 GetFramebuffer(client_ids[ii]);
3313 if (framebuffer && !framebuffer->IsDeleted()) {
3314 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3315 GLenum target = supports_separate_framebuffer_binds ?
3316 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3318 // Unbind attachments on FBO before deletion.
3319 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3320 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3322 glBindFramebufferEXT(target, GetBackbufferServiceId());
3323 framebuffer_state_.bound_draw_framebuffer = NULL;
3324 framebuffer_state_.clear_state_dirty = true;
3326 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3327 framebuffer_state_.bound_read_framebuffer = NULL;
3328 GLenum target = supports_separate_framebuffer_binds ?
3329 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3330 glBindFramebufferEXT(target, GetBackbufferServiceId());
3332 OnFboChanged();
3333 RemoveFramebuffer(client_ids[ii]);
3338 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3339 GLsizei n, const GLuint* client_ids) {
3340 bool supports_separate_framebuffer_binds =
3341 features().chromium_framebuffer_multisample;
3342 for (GLsizei ii = 0; ii < n; ++ii) {
3343 Renderbuffer* renderbuffer =
3344 GetRenderbuffer(client_ids[ii]);
3345 if (renderbuffer && !renderbuffer->IsDeleted()) {
3346 if (state_.bound_renderbuffer.get() == renderbuffer) {
3347 state_.bound_renderbuffer = NULL;
3349 // Unbind from current framebuffers.
3350 if (supports_separate_framebuffer_binds) {
3351 if (framebuffer_state_.bound_read_framebuffer.get()) {
3352 framebuffer_state_.bound_read_framebuffer
3353 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3355 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3356 framebuffer_state_.bound_draw_framebuffer
3357 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3359 } else {
3360 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3361 framebuffer_state_.bound_draw_framebuffer
3362 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3365 framebuffer_state_.clear_state_dirty = true;
3366 RemoveRenderbuffer(client_ids[ii]);
3371 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3372 GLsizei n,
3373 const GLuint* client_ids) {
3374 for (GLsizei ii = 0; ii < n; ++ii) {
3375 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3376 if (valuebuffer) {
3377 if (state_.bound_valuebuffer.get() == valuebuffer) {
3378 state_.bound_valuebuffer = NULL;
3380 RemoveValuebuffer(client_ids[ii]);
3385 void GLES2DecoderImpl::DeleteTexturesHelper(
3386 GLsizei n, const GLuint* client_ids) {
3387 bool supports_separate_framebuffer_binds =
3388 features().chromium_framebuffer_multisample;
3389 for (GLsizei ii = 0; ii < n; ++ii) {
3390 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3391 if (texture_ref) {
3392 Texture* texture = texture_ref->texture();
3393 if (texture->IsAttachedToFramebuffer()) {
3394 framebuffer_state_.clear_state_dirty = true;
3396 // Unbind texture_ref from texture_ref units.
3397 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3398 state_.texture_units[jj].Unbind(texture_ref);
3400 // Unbind from current framebuffers.
3401 if (supports_separate_framebuffer_binds) {
3402 if (framebuffer_state_.bound_read_framebuffer.get()) {
3403 framebuffer_state_.bound_read_framebuffer
3404 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3406 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3407 framebuffer_state_.bound_draw_framebuffer
3408 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3410 } else {
3411 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3412 framebuffer_state_.bound_draw_framebuffer
3413 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3416 #if defined(OS_MACOSX)
3417 GLuint service_id = texture->service_id();
3418 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3419 ReleaseIOSurfaceForTexture(service_id);
3421 #endif
3422 RemoveTexture(client_ids[ii]);
3427 // } // anonymous namespace
3429 bool GLES2DecoderImpl::MakeCurrent() {
3430 if (!context_.get())
3431 return false;
3433 if (WasContextLost()) {
3434 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3435 return false;
3438 if (!context_->MakeCurrent(surface_.get())) {
3439 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3440 MarkContextLost(error::kMakeCurrentFailed);
3441 group_->LoseContexts(error::kUnknown);
3442 return false;
3445 if (CheckResetStatus()) {
3446 LOG(ERROR)
3447 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3448 group_->LoseContexts(error::kUnknown);
3449 return false;
3452 ProcessFinishedAsyncTransfers();
3454 // Rebind the FBO if it was unbound by the context.
3455 if (workarounds().unbind_fbo_on_context_switch)
3456 RestoreFramebufferBindings();
3458 framebuffer_state_.clear_state_dirty = true;
3460 return true;
3463 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3464 ProcessPendingReadPixels();
3465 if (engine() && query_manager_.get())
3466 query_manager_->ProcessPendingTransferQueries();
3468 // TODO(epenner): Is there a better place to do this?
3469 // This needs to occur before we execute any batch of commands
3470 // from the client, as the client may have recieved an async
3471 // completion while issuing those commands.
3472 // "DidFlushStart" would be ideal if we had such a callback.
3473 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3476 static void RebindCurrentFramebuffer(
3477 GLenum target,
3478 Framebuffer* framebuffer,
3479 GLuint back_buffer_service_id) {
3480 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3482 if (framebuffer_id == 0) {
3483 framebuffer_id = back_buffer_service_id;
3486 glBindFramebufferEXT(target, framebuffer_id);
3489 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3490 framebuffer_state_.clear_state_dirty = true;
3492 if (!features().chromium_framebuffer_multisample) {
3493 RebindCurrentFramebuffer(
3494 GL_FRAMEBUFFER,
3495 framebuffer_state_.bound_draw_framebuffer.get(),
3496 GetBackbufferServiceId());
3497 } else {
3498 RebindCurrentFramebuffer(
3499 GL_READ_FRAMEBUFFER_EXT,
3500 framebuffer_state_.bound_read_framebuffer.get(),
3501 GetBackbufferServiceId());
3502 RebindCurrentFramebuffer(
3503 GL_DRAW_FRAMEBUFFER_EXT,
3504 framebuffer_state_.bound_draw_framebuffer.get(),
3505 GetBackbufferServiceId());
3507 OnFboChanged();
3510 bool GLES2DecoderImpl::CheckFramebufferValid(
3511 Framebuffer* framebuffer,
3512 GLenum target, const char* func_name) {
3513 if (!framebuffer) {
3514 if (surfaceless_)
3515 return false;
3516 if (backbuffer_needs_clear_bits_) {
3517 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3518 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3519 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3520 glClearStencil(0);
3521 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3522 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3523 glClearDepth(1.0f);
3524 state_.SetDeviceDepthMask(GL_TRUE);
3525 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3526 bool reset_draw_buffer = false;
3527 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3528 group_->draw_buffer() == GL_NONE) {
3529 reset_draw_buffer = true;
3530 GLenum buf = GL_BACK;
3531 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3532 buf = GL_COLOR_ATTACHMENT0;
3533 glDrawBuffersARB(1, &buf);
3535 glClear(backbuffer_needs_clear_bits_);
3536 if (reset_draw_buffer) {
3537 GLenum buf = GL_NONE;
3538 glDrawBuffersARB(1, &buf);
3540 backbuffer_needs_clear_bits_ = 0;
3541 RestoreClearState();
3543 return true;
3546 if (framebuffer_manager()->IsComplete(framebuffer)) {
3547 return true;
3550 GLenum completeness = framebuffer->IsPossiblyComplete();
3551 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3552 LOCAL_SET_GL_ERROR(
3553 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3554 return false;
3557 // Are all the attachments cleared?
3558 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3559 texture_manager()->HaveUnclearedMips()) {
3560 if (!framebuffer->IsCleared()) {
3561 // Can we clear them?
3562 if (framebuffer->GetStatus(texture_manager(), target) !=
3563 GL_FRAMEBUFFER_COMPLETE) {
3564 LOCAL_SET_GL_ERROR(
3565 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3566 "framebuffer incomplete (clear)");
3567 return false;
3569 ClearUnclearedAttachments(target, framebuffer);
3573 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3574 if (framebuffer->GetStatus(texture_manager(), target) !=
3575 GL_FRAMEBUFFER_COMPLETE) {
3576 LOCAL_SET_GL_ERROR(
3577 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3578 "framebuffer incomplete (check)");
3579 return false;
3581 framebuffer_manager()->MarkAsComplete(framebuffer);
3584 // NOTE: At this point we don't know if the framebuffer is complete but
3585 // we DO know that everything that needs to be cleared has been cleared.
3586 return true;
3589 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3590 if (!features().chromium_framebuffer_multisample) {
3591 bool valid = CheckFramebufferValid(
3592 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3593 func_name);
3595 if (valid)
3596 OnUseFramebuffer();
3598 return valid;
3600 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3601 GL_DRAW_FRAMEBUFFER_EXT,
3602 func_name) &&
3603 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3604 GL_READ_FRAMEBUFFER_EXT,
3605 func_name);
3608 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3609 const char* func_name) {
3610 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3611 framebuffer_state_.bound_read_framebuffer.get() :
3612 framebuffer_state_.bound_draw_framebuffer.get();
3613 if (!framebuffer)
3614 return true;
3615 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3616 LOCAL_SET_GL_ERROR(
3617 GL_INVALID_OPERATION, func_name, "no color image attached");
3618 return false;
3620 return true;
3623 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3624 TextureRef* texture, GLint level) {
3625 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3626 framebuffer_state_.bound_read_framebuffer.get() :
3627 framebuffer_state_.bound_draw_framebuffer.get();
3628 if (!framebuffer)
3629 return false;
3630 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3631 GL_COLOR_ATTACHMENT0);
3632 if (!attachment)
3633 return false;
3634 return attachment->FormsFeedbackLoop(texture, level);
3637 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3638 Framebuffer* framebuffer =
3639 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3640 if (framebuffer != NULL) {
3641 const Framebuffer::Attachment* attachment =
3642 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3643 if (attachment) {
3644 return gfx::Size(attachment->width(), attachment->height());
3646 return gfx::Size(0, 0);
3647 } else if (offscreen_target_frame_buffer_.get()) {
3648 return offscreen_size_;
3649 } else {
3650 return surface_->GetSize();
3654 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3655 Framebuffer* framebuffer =
3656 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3657 if (framebuffer != NULL) {
3658 return framebuffer->GetColorAttachmentTextureType();
3659 } else {
3660 return GL_UNSIGNED_BYTE;
3664 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3665 Framebuffer* framebuffer =
3666 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3667 if (framebuffer != NULL) {
3668 return framebuffer->GetColorAttachmentFormat();
3669 } else if (offscreen_target_frame_buffer_.get()) {
3670 return offscreen_target_color_format_;
3671 } else {
3672 return back_buffer_color_format_;
3676 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3677 Framebuffer* framebuffer =
3678 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3679 if (framebuffer != NULL) {
3680 return framebuffer->GetColorAttachmentFormat();
3681 } else if (offscreen_target_frame_buffer_.get()) {
3682 return offscreen_target_color_format_;
3683 } else {
3684 return back_buffer_color_format_;
3688 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3689 if (!offscreen_saved_color_texture_info_.get())
3690 return;
3691 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3692 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3693 texture_manager()->SetLevelInfo(
3694 offscreen_saved_color_texture_info_.get(),
3695 GL_TEXTURE_2D,
3696 0, // level
3697 GL_RGBA,
3698 offscreen_size_.width(),
3699 offscreen_size_.height(),
3700 1, // depth
3701 0, // border
3702 GL_RGBA,
3703 GL_UNSIGNED_BYTE,
3704 true);
3705 texture_manager()->SetParameteri(
3706 "UpdateParentTextureInfo",
3707 GetErrorState(),
3708 offscreen_saved_color_texture_info_.get(),
3709 GL_TEXTURE_MAG_FILTER,
3710 GL_LINEAR);
3711 texture_manager()->SetParameteri(
3712 "UpdateParentTextureInfo",
3713 GetErrorState(),
3714 offscreen_saved_color_texture_info_.get(),
3715 GL_TEXTURE_MIN_FILTER,
3716 GL_LINEAR);
3717 texture_manager()->SetParameteri(
3718 "UpdateParentTextureInfo",
3719 GetErrorState(),
3720 offscreen_saved_color_texture_info_.get(),
3721 GL_TEXTURE_WRAP_S,
3722 GL_CLAMP_TO_EDGE);
3723 texture_manager()->SetParameteri(
3724 "UpdateParentTextureInfo",
3725 GetErrorState(),
3726 offscreen_saved_color_texture_info_.get(),
3727 GL_TEXTURE_WRAP_T,
3728 GL_CLAMP_TO_EDGE);
3729 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3730 &state_, target);
3731 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3734 void GLES2DecoderImpl::SetResizeCallback(
3735 const base::Callback<void(gfx::Size, float)>& callback) {
3736 resize_callback_ = callback;
3739 Logger* GLES2DecoderImpl::GetLogger() {
3740 return &logger_;
3743 void GLES2DecoderImpl::BeginDecoding() {
3744 gpu_tracer_->BeginDecoding();
3745 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3746 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3747 (*cb_command_trace_category_ != 0);
3750 void GLES2DecoderImpl::EndDecoding() {
3751 gpu_tracer_->EndDecoding();
3754 ErrorState* GLES2DecoderImpl::GetErrorState() {
3755 return state_.GetErrorState();
3758 void GLES2DecoderImpl::SetShaderCacheCallback(
3759 const ShaderCacheCallback& callback) {
3760 shader_cache_callback_ = callback;
3763 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3764 const WaitSyncPointCallback& callback) {
3765 wait_sync_point_callback_ = callback;
3768 AsyncPixelTransferManager*
3769 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3770 return async_pixel_transfer_manager_.get();
3773 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3774 async_pixel_transfer_manager_.reset();
3777 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3778 AsyncPixelTransferManager* manager) {
3779 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3782 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3783 uint32* service_texture_id) {
3784 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3785 if (texture_ref) {
3786 *service_texture_id = texture_ref->service_id();
3787 return true;
3789 return false;
3792 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3793 return texture_state_.texture_upload_count +
3794 async_pixel_transfer_manager_->GetTextureUploadCount();
3797 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3798 return texture_state_.total_texture_upload_time +
3799 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3802 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3803 return total_processing_commands_time_;
3806 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3807 total_processing_commands_time_ += time;
3810 void GLES2DecoderImpl::Destroy(bool have_context) {
3811 if (!initialized())
3812 return;
3814 DCHECK(!have_context || context_->IsCurrent(NULL));
3816 // Unbind everything.
3817 state_.vertex_attrib_manager = NULL;
3818 state_.default_vertex_attrib_manager = NULL;
3819 state_.texture_units.clear();
3820 state_.bound_array_buffer = NULL;
3821 state_.bound_copy_read_buffer = NULL;
3822 state_.bound_copy_write_buffer = NULL;
3823 state_.bound_pixel_pack_buffer = NULL;
3824 state_.bound_pixel_unpack_buffer = NULL;
3825 state_.bound_transform_feedback_buffer = NULL;
3826 state_.bound_uniform_buffer = NULL;
3827 state_.current_queries.clear();
3828 framebuffer_state_.bound_read_framebuffer = NULL;
3829 framebuffer_state_.bound_draw_framebuffer = NULL;
3830 state_.bound_renderbuffer = NULL;
3831 state_.bound_valuebuffer = NULL;
3833 if (offscreen_saved_color_texture_info_.get()) {
3834 DCHECK(offscreen_target_color_texture_);
3835 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3836 offscreen_saved_color_texture_->id());
3837 offscreen_saved_color_texture_->Invalidate();
3838 offscreen_saved_color_texture_info_ = NULL;
3840 if (have_context) {
3841 if (copy_texture_CHROMIUM_.get()) {
3842 copy_texture_CHROMIUM_->Destroy();
3843 copy_texture_CHROMIUM_.reset();
3846 clear_framebuffer_blit_.reset();
3848 if (state_.current_program.get()) {
3849 program_manager()->UnuseProgram(shader_manager(),
3850 state_.current_program.get());
3853 if (attrib_0_buffer_id_) {
3854 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3856 if (fixed_attrib_buffer_id_) {
3857 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3860 if (validation_texture_) {
3861 glDeleteTextures(1, &validation_texture_);
3862 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3863 glDeleteFramebuffersEXT(1, &validation_fbo_);
3866 if (offscreen_target_frame_buffer_.get())
3867 offscreen_target_frame_buffer_->Destroy();
3868 if (offscreen_target_color_texture_.get())
3869 offscreen_target_color_texture_->Destroy();
3870 if (offscreen_target_color_render_buffer_.get())
3871 offscreen_target_color_render_buffer_->Destroy();
3872 if (offscreen_target_depth_render_buffer_.get())
3873 offscreen_target_depth_render_buffer_->Destroy();
3874 if (offscreen_target_stencil_render_buffer_.get())
3875 offscreen_target_stencil_render_buffer_->Destroy();
3876 if (offscreen_saved_frame_buffer_.get())
3877 offscreen_saved_frame_buffer_->Destroy();
3878 if (offscreen_saved_color_texture_.get())
3879 offscreen_saved_color_texture_->Destroy();
3880 if (offscreen_resolved_frame_buffer_.get())
3881 offscreen_resolved_frame_buffer_->Destroy();
3882 if (offscreen_resolved_color_texture_.get())
3883 offscreen_resolved_color_texture_->Destroy();
3884 } else {
3885 if (offscreen_target_frame_buffer_.get())
3886 offscreen_target_frame_buffer_->Invalidate();
3887 if (offscreen_target_color_texture_.get())
3888 offscreen_target_color_texture_->Invalidate();
3889 if (offscreen_target_color_render_buffer_.get())
3890 offscreen_target_color_render_buffer_->Invalidate();
3891 if (offscreen_target_depth_render_buffer_.get())
3892 offscreen_target_depth_render_buffer_->Invalidate();
3893 if (offscreen_target_stencil_render_buffer_.get())
3894 offscreen_target_stencil_render_buffer_->Invalidate();
3895 if (offscreen_saved_frame_buffer_.get())
3896 offscreen_saved_frame_buffer_->Invalidate();
3897 if (offscreen_saved_color_texture_.get())
3898 offscreen_saved_color_texture_->Invalidate();
3899 if (offscreen_resolved_frame_buffer_.get())
3900 offscreen_resolved_frame_buffer_->Invalidate();
3901 if (offscreen_resolved_color_texture_.get())
3902 offscreen_resolved_color_texture_->Invalidate();
3905 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3906 // Otherwise, we can leak objects. http://crbug.com/258772.
3907 // state_.current_program must be reset before group_ is reset because
3908 // the later deletes the ProgramManager object that referred by
3909 // state_.current_program object.
3910 state_.current_program = NULL;
3912 copy_texture_CHROMIUM_.reset();
3913 clear_framebuffer_blit_.reset();
3915 if (query_manager_.get()) {
3916 query_manager_->Destroy(have_context);
3917 query_manager_.reset();
3920 if (vertex_array_manager_ .get()) {
3921 vertex_array_manager_->Destroy(have_context);
3922 vertex_array_manager_.reset();
3925 if (image_manager_.get()) {
3926 image_manager_->Destroy(have_context);
3927 image_manager_.reset();
3930 offscreen_target_frame_buffer_.reset();
3931 offscreen_target_color_texture_.reset();
3932 offscreen_target_color_render_buffer_.reset();
3933 offscreen_target_depth_render_buffer_.reset();
3934 offscreen_target_stencil_render_buffer_.reset();
3935 offscreen_saved_frame_buffer_.reset();
3936 offscreen_saved_color_texture_.reset();
3937 offscreen_resolved_frame_buffer_.reset();
3938 offscreen_resolved_color_texture_.reset();
3940 // Need to release these before releasing |group_| which may own the
3941 // ShaderTranslatorCache.
3942 fragment_translator_ = NULL;
3943 vertex_translator_ = NULL;
3945 // Should destroy the transfer manager before the texture manager held
3946 // by the context group.
3947 async_pixel_transfer_manager_.reset();
3949 // Destroy the GPU Tracer which may own some in process GPU Timings.
3950 if (gpu_tracer_) {
3951 gpu_tracer_->Destroy(have_context);
3952 gpu_tracer_.reset();
3955 if (group_.get()) {
3956 framebuffer_manager()->RemoveObserver(this);
3957 group_->Destroy(this, have_context);
3958 group_ = NULL;
3961 if (context_.get()) {
3962 context_->ReleaseCurrent(NULL);
3963 context_ = NULL;
3966 #if defined(OS_MACOSX)
3967 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3968 it != texture_to_io_surface_map_.end(); ++it) {
3969 CFRelease(it->second);
3971 texture_to_io_surface_map_.clear();
3972 #endif
3975 void GLES2DecoderImpl::SetSurface(
3976 const scoped_refptr<gfx::GLSurface>& surface) {
3977 DCHECK(context_->IsCurrent(NULL));
3978 DCHECK(surface_.get());
3979 surface_ = surface;
3980 RestoreCurrentFramebufferBindings();
3983 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3984 if (!offscreen_saved_color_texture_.get()) {
3985 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3986 return;
3988 if (!offscreen_saved_color_texture_info_.get()) {
3989 GLuint service_id = offscreen_saved_color_texture_->id();
3990 offscreen_saved_color_texture_info_ = TextureRef::Create(
3991 texture_manager(), 0, service_id);
3992 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3993 GL_TEXTURE_2D);
3994 UpdateParentTextureInfo();
3996 mailbox_manager()->ProduceTexture(
3997 mailbox, offscreen_saved_color_texture_info_->texture());
4000 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4001 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4002 if (!is_offscreen) {
4003 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4004 << " with an onscreen framebuffer.";
4005 return false;
4008 if (offscreen_size_ == size)
4009 return true;
4011 offscreen_size_ = size;
4012 int w = offscreen_size_.width();
4013 int h = offscreen_size_.height();
4014 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4015 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4016 << "to allocate storage due to excessive dimensions.";
4017 return false;
4020 // Reallocate the offscreen target buffers.
4021 DCHECK(offscreen_target_color_format_);
4022 if (IsOffscreenBufferMultisampled()) {
4023 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4024 feature_info_.get(),
4025 offscreen_size_,
4026 offscreen_target_color_format_,
4027 offscreen_target_samples_)) {
4028 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4029 << "to allocate storage for offscreen target color buffer.";
4030 return false;
4032 } else {
4033 if (!offscreen_target_color_texture_->AllocateStorage(
4034 offscreen_size_, offscreen_target_color_format_, false)) {
4035 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4036 << "to allocate storage for offscreen target color texture.";
4037 return false;
4040 if (offscreen_target_depth_format_ &&
4041 !offscreen_target_depth_render_buffer_->AllocateStorage(
4042 feature_info_.get(),
4043 offscreen_size_,
4044 offscreen_target_depth_format_,
4045 offscreen_target_samples_)) {
4046 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4047 << "to allocate storage for offscreen target depth buffer.";
4048 return false;
4050 if (offscreen_target_stencil_format_ &&
4051 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4052 feature_info_.get(),
4053 offscreen_size_,
4054 offscreen_target_stencil_format_,
4055 offscreen_target_samples_)) {
4056 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4057 << "to allocate storage for offscreen target stencil buffer.";
4058 return false;
4061 // Attach the offscreen target buffers to the target frame buffer.
4062 if (IsOffscreenBufferMultisampled()) {
4063 offscreen_target_frame_buffer_->AttachRenderBuffer(
4064 GL_COLOR_ATTACHMENT0,
4065 offscreen_target_color_render_buffer_.get());
4066 } else {
4067 offscreen_target_frame_buffer_->AttachRenderTexture(
4068 offscreen_target_color_texture_.get());
4070 if (offscreen_target_depth_format_) {
4071 offscreen_target_frame_buffer_->AttachRenderBuffer(
4072 GL_DEPTH_ATTACHMENT,
4073 offscreen_target_depth_render_buffer_.get());
4075 const bool packed_depth_stencil =
4076 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4077 if (packed_depth_stencil) {
4078 offscreen_target_frame_buffer_->AttachRenderBuffer(
4079 GL_STENCIL_ATTACHMENT,
4080 offscreen_target_depth_render_buffer_.get());
4081 } else if (offscreen_target_stencil_format_) {
4082 offscreen_target_frame_buffer_->AttachRenderBuffer(
4083 GL_STENCIL_ATTACHMENT,
4084 offscreen_target_stencil_render_buffer_.get());
4087 if (offscreen_target_frame_buffer_->CheckStatus() !=
4088 GL_FRAMEBUFFER_COMPLETE) {
4089 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4090 << "because offscreen FBO was incomplete.";
4091 return false;
4094 // Clear the target frame buffer.
4096 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4097 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4098 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
4099 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4100 glClearStencil(0);
4101 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4102 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4103 glClearDepth(0);
4104 state_.SetDeviceDepthMask(GL_TRUE);
4105 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4106 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4107 RestoreClearState();
4110 // Destroy the offscreen resolved framebuffers.
4111 if (offscreen_resolved_frame_buffer_.get())
4112 offscreen_resolved_frame_buffer_->Destroy();
4113 if (offscreen_resolved_color_texture_.get())
4114 offscreen_resolved_color_texture_->Destroy();
4115 offscreen_resolved_color_texture_.reset();
4116 offscreen_resolved_frame_buffer_.reset();
4118 return true;
4121 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4122 const void* cmd_data) {
4123 const gles2::cmds::ResizeCHROMIUM& c =
4124 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4125 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4126 return error::kDeferCommandUntilLater;
4128 GLuint width = static_cast<GLuint>(c.width);
4129 GLuint height = static_cast<GLuint>(c.height);
4130 GLfloat scale_factor = c.scale_factor;
4131 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4133 width = std::max(1U, width);
4134 height = std::max(1U, height);
4136 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4137 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4138 // Make sure that we are done drawing to the back buffer before resizing.
4139 glFinish();
4140 #endif
4141 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4142 if (is_offscreen) {
4143 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4144 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4145 << "ResizeOffscreenFrameBuffer failed.";
4146 return error::kLostContext;
4150 if (!resize_callback_.is_null()) {
4151 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4152 DCHECK(context_->IsCurrent(surface_.get()));
4153 if (!context_->IsCurrent(surface_.get())) {
4154 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4155 << "current after resize callback.";
4156 return error::kLostContext;
4160 return error::kNoError;
4163 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4164 if (command_id > kStartPoint && command_id < kNumCommands) {
4165 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4167 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4170 // Decode a command, and call the corresponding GL functions.
4171 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4172 // of commands at once, and is now only used for tests that need to track
4173 // individual commands.
4174 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4175 unsigned int arg_count,
4176 const void* cmd_data) {
4177 return DoCommands(1, cmd_data, arg_count + 1, 0);
4180 // Decode multiple commands, and call the corresponding GL functions.
4181 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4182 // changed by a (malicious) client at any time, so if validation has to happen,
4183 // it should operate on a copy of them.
4184 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4185 // interest of performance in this critical execution loop.
4186 template <bool DebugImpl>
4187 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4188 const void* buffer,
4189 int num_entries,
4190 int* entries_processed) {
4191 commands_to_process_ = num_commands;
4192 error::Error result = error::kNoError;
4193 const CommandBufferEntry* cmd_data =
4194 static_cast<const CommandBufferEntry*>(buffer);
4195 int process_pos = 0;
4196 unsigned int command = 0;
4198 while (process_pos < num_entries && result == error::kNoError &&
4199 commands_to_process_--) {
4200 const unsigned int size = cmd_data->value_header.size;
4201 command = cmd_data->value_header.command;
4203 if (size == 0) {
4204 result = error::kInvalidSize;
4205 break;
4208 if (static_cast<int>(size) + process_pos > num_entries) {
4209 result = error::kOutOfBounds;
4210 break;
4213 if (DebugImpl) {
4214 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4215 GetCommandName(command));
4217 if (log_commands()) {
4218 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4219 << "cmd: " << GetCommandName(command);
4223 const unsigned int arg_count = size - 1;
4224 unsigned int command_index = command - kStartPoint - 1;
4225 if (command_index < arraysize(command_info)) {
4226 const CommandInfo& info = command_info[command_index];
4227 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4228 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4229 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4230 bool doing_gpu_trace = false;
4231 if (DebugImpl && gpu_trace_commands_) {
4232 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4233 doing_gpu_trace = true;
4234 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4235 GetCommandName(command),
4236 kTraceDecoder);
4240 uint32 immediate_data_size = (arg_count - info_arg_count) *
4241 sizeof(CommandBufferEntry); // NOLINT
4243 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4245 if (DebugImpl && doing_gpu_trace)
4246 gpu_tracer_->End(kTraceDecoder);
4248 if (DebugImpl && debug()) {
4249 GLenum error;
4250 while ((error = glGetError()) != GL_NO_ERROR) {
4251 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4252 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4253 << " : " << GetCommandName(command);
4254 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4257 } else {
4258 result = error::kInvalidArguments;
4260 } else {
4261 result = DoCommonCommand(command, arg_count, cmd_data);
4264 if (DebugImpl) {
4265 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4266 GetCommandName(command));
4269 if (result == error::kNoError &&
4270 current_decoder_error_ != error::kNoError) {
4271 result = current_decoder_error_;
4272 current_decoder_error_ = error::kNoError;
4275 if (result != error::kDeferCommandUntilLater) {
4276 process_pos += size;
4277 cmd_data += size;
4281 if (entries_processed)
4282 *entries_processed = process_pos;
4284 if (error::IsError(result)) {
4285 LOG(ERROR) << "Error: " << result << " for Command "
4286 << GetCommandName(command);
4289 return result;
4292 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4293 const void* buffer,
4294 int num_entries,
4295 int* entries_processed) {
4296 if (gpu_debug_commands_) {
4297 return DoCommandsImpl<true>(
4298 num_commands, buffer, num_entries, entries_processed);
4299 } else {
4300 return DoCommandsImpl<false>(
4301 num_commands, buffer, num_entries, entries_processed);
4305 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4306 buffer_manager()->RemoveBuffer(client_id);
4309 void GLES2DecoderImpl::DoFinish() {
4310 glFinish();
4311 ProcessPendingReadPixels();
4312 ProcessPendingQueries(true);
4315 void GLES2DecoderImpl::DoFlush() {
4316 glFlush();
4317 ProcessPendingQueries(false);
4320 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4321 GLuint texture_index = texture_unit - GL_TEXTURE0;
4322 if (texture_index >= state_.texture_units.size()) {
4323 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4324 "glActiveTexture", texture_unit, "texture_unit");
4325 return;
4327 state_.active_texture_unit = texture_index;
4328 glActiveTexture(texture_unit);
4331 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4332 Buffer* buffer = NULL;
4333 GLuint service_id = 0;
4334 if (client_id != 0) {
4335 buffer = GetBuffer(client_id);
4336 if (!buffer) {
4337 if (!group_->bind_generates_resource()) {
4338 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4339 "glBindBuffer",
4340 "id not generated by glGenBuffers");
4341 return;
4344 // It's a new id so make a buffer buffer for it.
4345 glGenBuffersARB(1, &service_id);
4346 CreateBuffer(client_id, service_id);
4347 buffer = GetBuffer(client_id);
4350 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4351 if (buffer) {
4352 if (!buffer_manager()->SetTarget(buffer, target)) {
4353 LOCAL_SET_GL_ERROR(
4354 GL_INVALID_OPERATION,
4355 "glBindBuffer", "buffer bound to more than 1 target");
4356 return;
4358 service_id = buffer->service_id();
4360 state_.SetBoundBuffer(target, buffer);
4361 glBindBuffer(target, service_id);
4364 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4365 bool all_draw_buffers) {
4366 Framebuffer* framebuffer =
4367 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4368 if (!all_draw_buffers || !framebuffer) {
4369 return (GLES2Util::GetChannelsForFormat(
4370 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4372 return framebuffer->HasAlphaMRT();
4375 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4376 Framebuffer* framebuffer =
4377 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4378 if (framebuffer) {
4379 return framebuffer->HasDepthAttachment();
4381 if (offscreen_target_frame_buffer_.get()) {
4382 return offscreen_target_depth_format_ != 0;
4384 return back_buffer_has_depth_;
4387 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4388 Framebuffer* framebuffer =
4389 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4390 if (framebuffer) {
4391 return framebuffer->HasStencilAttachment();
4393 if (offscreen_target_frame_buffer_.get()) {
4394 return offscreen_target_stencil_format_ != 0 ||
4395 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4397 return back_buffer_has_stencil_;
4400 void GLES2DecoderImpl::ApplyDirtyState() {
4401 if (framebuffer_state_.clear_state_dirty) {
4402 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4403 state_.SetDeviceColorMask(state_.color_mask_red,
4404 state_.color_mask_green,
4405 state_.color_mask_blue,
4406 state_.color_mask_alpha && have_alpha);
4408 bool have_depth = BoundFramebufferHasDepthAttachment();
4409 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4411 bool have_stencil = BoundFramebufferHasStencilAttachment();
4412 state_.SetDeviceStencilMaskSeparate(
4413 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4414 state_.SetDeviceStencilMaskSeparate(
4415 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4417 state_.SetDeviceCapabilityState(
4418 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4419 state_.SetDeviceCapabilityState(
4420 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4421 framebuffer_state_.clear_state_dirty = false;
4425 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4426 return (offscreen_target_frame_buffer_.get())
4427 ? offscreen_target_frame_buffer_->id()
4428 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4431 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4432 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4433 "context", logger_.GetLogPrefix());
4434 // Restore the Framebuffer first because of bugs in Intel drivers.
4435 // Intel drivers incorrectly clip the viewport settings to
4436 // the size of the current framebuffer object.
4437 RestoreFramebufferBindings();
4438 state_.RestoreState(prev_state);
4441 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4442 GLuint service_id =
4443 framebuffer_state_.bound_draw_framebuffer.get()
4444 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4445 : GetBackbufferServiceId();
4446 if (!features().chromium_framebuffer_multisample) {
4447 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4448 } else {
4449 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4450 service_id = framebuffer_state_.bound_read_framebuffer.get()
4451 ? framebuffer_state_.bound_read_framebuffer->service_id()
4452 : GetBackbufferServiceId();
4453 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4455 OnFboChanged();
4458 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4459 state_.RestoreRenderbufferBindings();
4462 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4463 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4464 if (texture) {
4465 GLenum target = texture->target();
4466 glBindTexture(target, service_id);
4467 glTexParameteri(
4468 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4469 glTexParameteri(
4470 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4471 glTexParameteri(
4472 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4473 glTexParameteri(
4474 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4475 RestoreTextureUnitBindings(state_.active_texture_unit);
4479 void GLES2DecoderImpl::ClearAllAttributes() const {
4480 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4481 // other VAOs.
4482 if (feature_info_->feature_flags().native_vertex_array_object)
4483 glBindVertexArrayOES(0);
4485 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4486 if (i != 0) // Never disable attribute 0
4487 glDisableVertexAttribArray(i);
4488 if (features().angle_instanced_arrays)
4489 glVertexAttribDivisorANGLE(i, 0);
4493 void GLES2DecoderImpl::RestoreAllAttributes() const {
4494 state_.RestoreVertexAttribs();
4497 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4498 state_.SetIgnoreCachedStateForTest(ignore);
4501 void GLES2DecoderImpl::SetAllowExit(bool allow_exit) {
4502 allow_exit_ = allow_exit;
4505 void GLES2DecoderImpl::OnFboChanged() const {
4506 if (workarounds().restore_scissor_on_fbo_change)
4507 state_.fbo_binding_for_scissor_workaround_dirty = true;
4509 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4510 GLint bound_fbo_unsigned = -1;
4511 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4512 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4513 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4514 surface_->NotifyWasBound();
4518 // Called after the FBO is checked for completeness.
4519 void GLES2DecoderImpl::OnUseFramebuffer() const {
4520 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4521 state_.fbo_binding_for_scissor_workaround_dirty = false;
4522 // The driver forgets the correct scissor when modifying the FBO binding.
4523 glScissor(state_.scissor_x,
4524 state_.scissor_y,
4525 state_.scissor_width,
4526 state_.scissor_height);
4528 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4529 // it's unclear how this bug works.
4530 glFlush();
4534 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4535 Framebuffer* framebuffer = NULL;
4536 GLuint service_id = 0;
4537 if (client_id != 0) {
4538 framebuffer = GetFramebuffer(client_id);
4539 if (!framebuffer) {
4540 if (!group_->bind_generates_resource()) {
4541 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4542 "glBindFramebuffer",
4543 "id not generated by glGenFramebuffers");
4544 return;
4547 // It's a new id so make a framebuffer framebuffer for it.
4548 glGenFramebuffersEXT(1, &service_id);
4549 CreateFramebuffer(client_id, service_id);
4550 framebuffer = GetFramebuffer(client_id);
4551 } else {
4552 service_id = framebuffer->service_id();
4554 framebuffer->MarkAsValid();
4556 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4558 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4559 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4562 // vmiura: This looks like dup code
4563 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4564 framebuffer_state_.bound_read_framebuffer = framebuffer;
4567 framebuffer_state_.clear_state_dirty = true;
4569 // If we are rendering to the backbuffer get the FBO id for any simulated
4570 // backbuffer.
4571 if (framebuffer == NULL) {
4572 service_id = GetBackbufferServiceId();
4575 glBindFramebufferEXT(target, service_id);
4576 OnFboChanged();
4579 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4580 Renderbuffer* renderbuffer = NULL;
4581 GLuint service_id = 0;
4582 if (client_id != 0) {
4583 renderbuffer = GetRenderbuffer(client_id);
4584 if (!renderbuffer) {
4585 if (!group_->bind_generates_resource()) {
4586 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4587 "glBindRenderbuffer",
4588 "id not generated by glGenRenderbuffers");
4589 return;
4592 // It's a new id so make a renderbuffer for it.
4593 glGenRenderbuffersEXT(1, &service_id);
4594 CreateRenderbuffer(client_id, service_id);
4595 renderbuffer = GetRenderbuffer(client_id);
4596 } else {
4597 service_id = renderbuffer->service_id();
4599 renderbuffer->MarkAsValid();
4601 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4602 state_.bound_renderbuffer = renderbuffer;
4603 state_.bound_renderbuffer_valid = true;
4604 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4607 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4608 TextureRef* texture_ref = NULL;
4609 GLuint service_id = 0;
4610 if (client_id != 0) {
4611 texture_ref = GetTexture(client_id);
4612 if (!texture_ref) {
4613 if (!group_->bind_generates_resource()) {
4614 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4615 "glBindTexture",
4616 "id not generated by glGenTextures");
4617 return;
4620 // It's a new id so make a texture texture for it.
4621 glGenTextures(1, &service_id);
4622 DCHECK_NE(0u, service_id);
4623 CreateTexture(client_id, service_id);
4624 texture_ref = GetTexture(client_id);
4626 } else {
4627 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4630 // Check the texture exists
4631 if (texture_ref) {
4632 Texture* texture = texture_ref->texture();
4633 // Check that we are not trying to bind it to a different target.
4634 if (texture->target() != 0 && texture->target() != target) {
4635 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4636 "glBindTexture",
4637 "texture bound to more than 1 target.");
4638 return;
4640 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4641 if (texture->target() == 0) {
4642 texture_manager()->SetTarget(texture_ref, target);
4644 glBindTexture(target, texture->service_id());
4645 } else {
4646 glBindTexture(target, 0);
4649 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4650 unit.bind_target = target;
4651 switch (target) {
4652 case GL_TEXTURE_2D:
4653 unit.bound_texture_2d = texture_ref;
4654 break;
4655 case GL_TEXTURE_CUBE_MAP:
4656 unit.bound_texture_cube_map = texture_ref;
4657 break;
4658 case GL_TEXTURE_EXTERNAL_OES:
4659 unit.bound_texture_external_oes = texture_ref;
4660 break;
4661 case GL_TEXTURE_RECTANGLE_ARB:
4662 unit.bound_texture_rectangle_arb = texture_ref;
4663 break;
4664 case GL_TEXTURE_3D:
4665 unit.bound_texture_3d = texture_ref;
4666 break;
4667 case GL_TEXTURE_2D_ARRAY:
4668 unit.bound_texture_2d_array = texture_ref;
4669 break;
4670 default:
4671 NOTREACHED(); // Validation should prevent us getting here.
4672 break;
4676 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4677 if (state_.vertex_attrib_manager->Enable(index, false)) {
4678 if (index != 0 ||
4679 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4680 glDisableVertexAttribArray(index);
4682 } else {
4683 LOCAL_SET_GL_ERROR(
4684 GL_INVALID_VALUE,
4685 "glDisableVertexAttribArray", "index out of range");
4689 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4690 GLsizei numAttachments,
4691 const GLenum* attachments) {
4692 if (workarounds().disable_discard_framebuffer)
4693 return;
4695 Framebuffer* framebuffer =
4696 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4698 // Validates the attachments. If one of them fails
4699 // the whole command fails.
4700 for (GLsizei i = 0; i < numAttachments; ++i) {
4701 if ((framebuffer &&
4702 !validators_->attachment.IsValid(attachments[i])) ||
4703 (!framebuffer &&
4704 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4705 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4706 "glDiscardFramebufferEXT", attachments[i], "attachments");
4707 return;
4711 // Marks each one of them as not cleared
4712 for (GLsizei i = 0; i < numAttachments; ++i) {
4713 if (framebuffer) {
4714 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4715 texture_manager(),
4716 attachments[i],
4717 false);
4718 } else {
4719 switch (attachments[i]) {
4720 case GL_COLOR_EXT:
4721 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4722 break;
4723 case GL_DEPTH_EXT:
4724 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4725 case GL_STENCIL_EXT:
4726 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4727 break;
4728 default:
4729 NOTREACHED();
4730 break;
4735 // If the default framebuffer is bound but we are still rendering to an
4736 // FBO, translate attachment names that refer to default framebuffer
4737 // channels to corresponding framebuffer attachments.
4738 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4739 for (GLsizei i = 0; i < numAttachments; ++i) {
4740 GLenum attachment = attachments[i];
4741 if (!framebuffer && GetBackbufferServiceId()) {
4742 switch (attachment) {
4743 case GL_COLOR_EXT:
4744 attachment = GL_COLOR_ATTACHMENT0;
4745 break;
4746 case GL_DEPTH_EXT:
4747 attachment = GL_DEPTH_ATTACHMENT;
4748 break;
4749 case GL_STENCIL_EXT:
4750 attachment = GL_STENCIL_ATTACHMENT;
4751 break;
4752 default:
4753 NOTREACHED();
4754 return;
4757 translated_attachments[i] = attachment;
4760 ScopedRenderTo do_render(framebuffer);
4761 if (feature_info_->gl_version_info().is_es3) {
4762 glInvalidateFramebuffer(
4763 target, numAttachments, translated_attachments.get());
4764 } else {
4765 glDiscardFramebufferEXT(
4766 target, numAttachments, translated_attachments.get());
4770 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4771 if (state_.vertex_attrib_manager->Enable(index, true)) {
4772 glEnableVertexAttribArray(index);
4773 } else {
4774 LOCAL_SET_GL_ERROR(
4775 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4779 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4780 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4781 &state_, target);
4782 if (!texture_ref ||
4783 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4784 LOCAL_SET_GL_ERROR(
4785 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4786 return;
4789 if (target == GL_TEXTURE_CUBE_MAP) {
4790 for (int i = 0; i < 6; ++i) {
4791 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4792 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4793 LOCAL_SET_GL_ERROR(
4794 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4795 return;
4798 } else {
4799 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4800 LOCAL_SET_GL_ERROR(
4801 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4802 return;
4806 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4807 // Workaround for Mac driver bug. In the large scheme of things setting
4808 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4809 // hit so there's probably no need to make this conditional. The bug appears
4810 // to be that if the filtering mode is set to something that doesn't require
4811 // mipmaps for rendering, or is never set to something other than the default,
4812 // then glGenerateMipmap misbehaves.
4813 if (workarounds().set_texture_filter_before_generating_mipmap) {
4814 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4816 glGenerateMipmapEXT(target);
4817 if (workarounds().set_texture_filter_before_generating_mipmap) {
4818 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4819 texture_ref->texture()->min_filter());
4821 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4822 if (error == GL_NO_ERROR) {
4823 texture_manager()->MarkMipmapsGenerated(texture_ref);
4827 bool GLES2DecoderImpl::GetHelper(
4828 GLenum pname, GLint* params, GLsizei* num_written) {
4829 DCHECK(num_written);
4830 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4831 switch (pname) {
4832 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4833 *num_written = 1;
4834 // Return the GL implementation's preferred format and (see below type)
4835 // if we have the GL extension that exposes this. This allows the GPU
4836 // client to use the implementation's preferred format for glReadPixels
4837 // for optimisation.
4839 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4840 // case when requested on integer/floating point buffers but which is
4841 // acceptable on GLES2 and with the GL_OES_read_format extension.
4843 // Therefore if an error occurs we swallow the error and use the
4844 // internal implementation.
4845 if (params) {
4846 if (context_->HasExtension("GL_OES_read_format")) {
4847 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4848 GetErrorState());
4849 glGetIntegerv(pname, params);
4850 if (glGetError() == GL_NO_ERROR)
4851 return true;
4853 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4854 GetBoundReadFrameBufferInternalFormat());
4856 return true;
4857 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4858 *num_written = 1;
4859 if (params) {
4860 if (context_->HasExtension("GL_OES_read_format")) {
4861 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4862 GetErrorState());
4863 glGetIntegerv(pname, params);
4864 if (glGetError() == GL_NO_ERROR)
4865 return true;
4867 *params = GLES2Util::GetPreferredGLReadPixelsType(
4868 GetBoundReadFrameBufferInternalFormat(),
4869 GetBoundReadFrameBufferTextureType());
4871 return true;
4872 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4873 *num_written = 1;
4874 if (params) {
4875 *params = group_->max_fragment_uniform_vectors();
4877 return true;
4878 case GL_MAX_VARYING_VECTORS:
4879 *num_written = 1;
4880 if (params) {
4881 *params = group_->max_varying_vectors();
4883 return true;
4884 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4885 *num_written = 1;
4886 if (params) {
4887 *params = group_->max_vertex_uniform_vectors();
4889 return true;
4892 if (unsafe_es3_apis_enabled()) {
4893 switch (pname) {
4894 case GL_MAX_VARYING_COMPONENTS: {
4895 if (feature_info_->gl_version_info().is_es) {
4896 // We can just delegate this query to the driver.
4897 return false;
4900 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
4901 // OpenGL core profile, so for simplicity, just compute it
4902 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
4903 // configurations.
4904 GLint max_varying_vectors = 0;
4905 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
4906 *num_written = 1;
4907 if (params) {
4908 *params = max_varying_vectors * 4;
4910 return true;
4914 switch (pname) {
4915 case GL_MAX_VIEWPORT_DIMS:
4916 if (offscreen_target_frame_buffer_.get()) {
4917 *num_written = 2;
4918 if (params) {
4919 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4920 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4922 return true;
4924 return false;
4925 case GL_MAX_SAMPLES:
4926 *num_written = 1;
4927 if (params) {
4928 params[0] = renderbuffer_manager()->max_samples();
4930 return true;
4931 case GL_MAX_RENDERBUFFER_SIZE:
4932 *num_written = 1;
4933 if (params) {
4934 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4936 return true;
4937 case GL_MAX_TEXTURE_SIZE:
4938 *num_written = 1;
4939 if (params) {
4940 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4942 return true;
4943 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4944 *num_written = 1;
4945 if (params) {
4946 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4948 return true;
4949 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4950 *num_written = 1;
4951 if (params) {
4952 params[0] = group_->max_color_attachments();
4954 return true;
4955 case GL_MAX_DRAW_BUFFERS_ARB:
4956 *num_written = 1;
4957 if (params) {
4958 params[0] = group_->max_draw_buffers();
4960 return true;
4961 case GL_ALPHA_BITS:
4962 *num_written = 1;
4963 if (params) {
4964 GLint v = 0;
4965 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4966 Framebuffer* framebuffer =
4967 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4968 if (framebuffer) {
4969 glGetFramebufferAttachmentParameterivEXT(
4970 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4971 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
4972 } else {
4973 v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0);
4975 } else {
4976 glGetIntegerv(GL_ALPHA_BITS, &v);
4978 params[0] =
4979 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4981 return true;
4982 case GL_DEPTH_BITS:
4983 *num_written = 1;
4984 if (params) {
4985 GLint v = 0;
4986 if (feature_info_->gl_version_info().is_desktop_core_profile) {
4987 Framebuffer* framebuffer =
4988 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4989 if (framebuffer) {
4990 glGetFramebufferAttachmentParameterivEXT(
4991 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
4992 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
4993 } else {
4994 v = (back_buffer_has_depth_ ? 24 : 0);
4996 } else {
4997 glGetIntegerv(GL_DEPTH_BITS, &v);
4999 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5001 return true;
5002 case GL_RED_BITS:
5003 case GL_GREEN_BITS:
5004 case GL_BLUE_BITS:
5005 *num_written = 1;
5006 if (params) {
5007 GLint v = 0;
5008 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5009 Framebuffer* framebuffer =
5010 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5011 if (framebuffer) {
5012 GLenum framebuffer_enum = 0;
5013 switch (pname) {
5014 case GL_RED_BITS:
5015 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5016 break;
5017 case GL_GREEN_BITS:
5018 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5019 break;
5020 case GL_BLUE_BITS:
5021 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5022 break;
5024 glGetFramebufferAttachmentParameterivEXT(
5025 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5026 } else {
5027 v = 8;
5029 } else {
5030 glGetIntegerv(pname, &v);
5032 params[0] = v;
5034 return true;
5035 case GL_STENCIL_BITS:
5036 *num_written = 1;
5037 if (params) {
5038 GLint v = 0;
5039 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5040 Framebuffer* framebuffer =
5041 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5042 if (framebuffer) {
5043 glGetFramebufferAttachmentParameterivEXT(
5044 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5045 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5046 } else {
5047 v = (back_buffer_has_stencil_ ? 8 : 0);
5049 } else {
5050 glGetIntegerv(GL_STENCIL_BITS, &v);
5052 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5054 return true;
5055 case GL_COMPRESSED_TEXTURE_FORMATS:
5056 *num_written = validators_->compressed_texture_format.GetValues().size();
5057 if (params) {
5058 for (GLint ii = 0; ii < *num_written; ++ii) {
5059 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5062 return true;
5063 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5064 *num_written = 1;
5065 if (params) {
5066 *params = validators_->compressed_texture_format.GetValues().size();
5068 return true;
5069 case GL_NUM_SHADER_BINARY_FORMATS:
5070 *num_written = 1;
5071 if (params) {
5072 *params = validators_->shader_binary_format.GetValues().size();
5074 return true;
5075 case GL_SHADER_BINARY_FORMATS:
5076 *num_written = validators_->shader_binary_format.GetValues().size();
5077 if (params) {
5078 for (GLint ii = 0; ii < *num_written; ++ii) {
5079 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5082 return true;
5083 case GL_SHADER_COMPILER:
5084 *num_written = 1;
5085 if (params) {
5086 *params = GL_TRUE;
5088 return true;
5089 case GL_ARRAY_BUFFER_BINDING:
5090 *num_written = 1;
5091 if (params) {
5092 *params = GetClientId(
5093 buffer_manager(), state_.bound_array_buffer.get());
5095 return true;
5096 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5097 *num_written = 1;
5098 if (params) {
5099 *params = GetClientId(
5100 buffer_manager(),
5101 state_.vertex_attrib_manager->element_array_buffer());
5103 return true;
5104 case GL_COPY_READ_BUFFER_BINDING:
5105 *num_written = 1;
5106 if (params) {
5107 *params = GetClientId(
5108 buffer_manager(), state_.bound_copy_read_buffer.get());
5110 return true;
5111 case GL_COPY_WRITE_BUFFER_BINDING:
5112 *num_written = 1;
5113 if (params) {
5114 *params = GetClientId(
5115 buffer_manager(), state_.bound_copy_write_buffer.get());
5117 return true;
5118 case GL_PIXEL_PACK_BUFFER_BINDING:
5119 *num_written = 1;
5120 if (params) {
5121 *params = GetClientId(
5122 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5124 return true;
5125 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5126 *num_written = 1;
5127 if (params) {
5128 *params = GetClientId(
5129 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5131 return true;
5132 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5133 *num_written = 1;
5134 if (params) {
5135 *params = GetClientId(
5136 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5138 return true;
5139 case GL_UNIFORM_BUFFER_BINDING:
5140 *num_written = 1;
5141 if (params) {
5142 *params = GetClientId(
5143 buffer_manager(), state_.bound_uniform_buffer.get());
5145 return true;
5146 case GL_FRAMEBUFFER_BINDING:
5147 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5148 *num_written = 1;
5149 if (params) {
5150 *params = GetClientId(
5151 framebuffer_manager(),
5152 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5154 return true;
5155 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5156 *num_written = 1;
5157 if (params) {
5158 *params = GetClientId(
5159 framebuffer_manager(),
5160 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5162 return true;
5163 case GL_RENDERBUFFER_BINDING:
5164 *num_written = 1;
5165 if (params) {
5166 Renderbuffer* renderbuffer =
5167 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5168 if (renderbuffer) {
5169 *params = renderbuffer->client_id();
5170 } else {
5171 *params = 0;
5174 return true;
5175 case GL_CURRENT_PROGRAM:
5176 *num_written = 1;
5177 if (params) {
5178 *params = GetClientId(program_manager(), state_.current_program.get());
5180 return true;
5181 case GL_VERTEX_ARRAY_BINDING_OES:
5182 *num_written = 1;
5183 if (params) {
5184 if (state_.vertex_attrib_manager.get() !=
5185 state_.default_vertex_attrib_manager.get()) {
5186 GLuint client_id = 0;
5187 vertex_array_manager_->GetClientId(
5188 state_.vertex_attrib_manager->service_id(), &client_id);
5189 *params = client_id;
5190 } else {
5191 *params = 0;
5194 return true;
5195 case GL_TEXTURE_BINDING_2D:
5196 *num_written = 1;
5197 if (params) {
5198 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5199 if (unit.bound_texture_2d.get()) {
5200 *params = unit.bound_texture_2d->client_id();
5201 } else {
5202 *params = 0;
5205 return true;
5206 case GL_TEXTURE_BINDING_CUBE_MAP:
5207 *num_written = 1;
5208 if (params) {
5209 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5210 if (unit.bound_texture_cube_map.get()) {
5211 *params = unit.bound_texture_cube_map->client_id();
5212 } else {
5213 *params = 0;
5216 return true;
5217 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5218 *num_written = 1;
5219 if (params) {
5220 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5221 if (unit.bound_texture_external_oes.get()) {
5222 *params = unit.bound_texture_external_oes->client_id();
5223 } else {
5224 *params = 0;
5227 return true;
5228 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5229 *num_written = 1;
5230 if (params) {
5231 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5232 if (unit.bound_texture_rectangle_arb.get()) {
5233 *params = unit.bound_texture_rectangle_arb->client_id();
5234 } else {
5235 *params = 0;
5238 return true;
5239 case GL_UNPACK_FLIP_Y_CHROMIUM:
5240 *num_written = 1;
5241 if (params) {
5242 params[0] = unpack_flip_y_;
5244 return true;
5245 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
5246 *num_written = 1;
5247 if (params) {
5248 params[0] = unpack_premultiply_alpha_;
5250 return true;
5251 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
5252 *num_written = 1;
5253 if (params) {
5254 params[0] = unpack_unpremultiply_alpha_;
5256 return true;
5257 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5258 *num_written = 1;
5259 if (params) {
5260 params[0] = group_->bind_generates_resource() ? 1 : 0;
5262 return true;
5263 default:
5264 if (pname >= GL_DRAW_BUFFER0_ARB &&
5265 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5266 *num_written = 1;
5267 if (params) {
5268 Framebuffer* framebuffer =
5269 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5270 if (framebuffer) {
5271 params[0] = framebuffer->GetDrawBuffer(pname);
5272 } else { // backbuffer
5273 if (pname == GL_DRAW_BUFFER0_ARB)
5274 params[0] = group_->draw_buffer();
5275 else
5276 params[0] = GL_NONE;
5279 return true;
5281 *num_written = util_.GLGetNumValuesReturned(pname);
5282 return false;
5286 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5287 GLenum pname, GLsizei* num_values) {
5288 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5289 return true;
5291 return GetHelper(pname, NULL, num_values);
5294 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5295 if (GL_MAX_SAMPLES == pname &&
5296 features().use_img_for_multisampled_render_to_texture) {
5297 return GL_MAX_SAMPLES_IMG;
5299 return pname;
5302 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5303 DCHECK(params);
5304 GLsizei num_written = 0;
5305 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5306 scoped_ptr<GLint[]> values(new GLint[num_written]);
5307 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5308 GetHelper(pname, values.get(), &num_written);
5310 for (GLsizei ii = 0; ii < num_written; ++ii) {
5311 params[ii] = static_cast<GLboolean>(values[ii]);
5313 } else {
5314 pname = AdjustGetPname(pname);
5315 glGetBooleanv(pname, params);
5319 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5320 DCHECK(params);
5321 GLsizei num_written = 0;
5322 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5323 if (GetHelper(pname, NULL, &num_written)) {
5324 scoped_ptr<GLint[]> values(new GLint[num_written]);
5325 GetHelper(pname, values.get(), &num_written);
5326 for (GLsizei ii = 0; ii < num_written; ++ii) {
5327 params[ii] = static_cast<GLfloat>(values[ii]);
5329 } else {
5330 pname = AdjustGetPname(pname);
5331 glGetFloatv(pname, params);
5336 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5337 DCHECK(params);
5338 if (unsafe_es3_apis_enabled()) {
5339 switch (pname) {
5340 case GL_MAX_ELEMENT_INDEX: {
5341 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5342 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5343 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5344 } else {
5345 // Assume that desktop GL implementations can generally support
5346 // 32-bit indices.
5347 if (params) {
5348 *params = std::numeric_limits<unsigned int>::max();
5351 return;
5355 pname = AdjustGetPname(pname);
5356 glGetInteger64v(pname, params);
5359 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5360 DCHECK(params);
5361 GLsizei num_written;
5362 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5363 !GetHelper(pname, params, &num_written)) {
5364 pname = AdjustGetPname(pname);
5365 glGetIntegerv(pname, params);
5369 void GLES2DecoderImpl::DoGetProgramiv(
5370 GLuint program_id, GLenum pname, GLint* params) {
5371 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5372 if (!program) {
5373 return;
5375 program->GetProgramiv(pname, params);
5378 void GLES2DecoderImpl::DoGetBufferParameteriv(
5379 GLenum target, GLenum pname, GLint* params) {
5380 // Just delegate it. Some validation is actually done before this.
5381 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5382 &state_, target, pname, params);
5385 void GLES2DecoderImpl::DoBindAttribLocation(
5386 GLuint program_id, GLuint index, const char* name) {
5387 if (!StringIsValidForGLES(name)) {
5388 LOCAL_SET_GL_ERROR(
5389 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5390 return;
5392 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5393 LOCAL_SET_GL_ERROR(
5394 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5395 return;
5397 if (index >= group_->max_vertex_attribs()) {
5398 LOCAL_SET_GL_ERROR(
5399 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5400 return;
5402 Program* program = GetProgramInfoNotShader(
5403 program_id, "glBindAttribLocation");
5404 if (!program) {
5405 return;
5407 // At this point, the program's shaders may not be translated yet,
5408 // therefore, we may not find the hashed attribute name.
5409 // glBindAttribLocation call with original name is useless.
5410 // So instead, we should simply cache the binding, and then call
5411 // Program::ExecuteBindAttribLocationCalls() right before link.
5412 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5413 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5414 glBindAttribLocation(program->service_id(), index, name);
5417 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5418 uint32 immediate_data_size,
5419 const void* cmd_data) {
5420 const gles2::cmds::BindAttribLocationBucket& c =
5421 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5422 GLuint program = static_cast<GLuint>(c.program);
5423 GLuint index = static_cast<GLuint>(c.index);
5424 Bucket* bucket = GetBucket(c.name_bucket_id);
5425 if (!bucket || bucket->size() == 0) {
5426 return error::kInvalidArguments;
5428 std::string name_str;
5429 if (!bucket->GetAsString(&name_str)) {
5430 return error::kInvalidArguments;
5432 DoBindAttribLocation(program, index, name_str.c_str());
5433 return error::kNoError;
5436 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5437 GLuint program_id, GLint location, const char* name) {
5438 if (!StringIsValidForGLES(name)) {
5439 LOCAL_SET_GL_ERROR(
5440 GL_INVALID_VALUE,
5441 "glBindUniformLocationCHROMIUM", "Invalid character");
5442 return;
5444 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5445 LOCAL_SET_GL_ERROR(
5446 GL_INVALID_OPERATION,
5447 "glBindUniformLocationCHROMIUM", "reserved prefix");
5448 return;
5450 if (location < 0 || static_cast<uint32>(location) >=
5451 (group_->max_fragment_uniform_vectors() +
5452 group_->max_vertex_uniform_vectors()) * 4) {
5453 LOCAL_SET_GL_ERROR(
5454 GL_INVALID_VALUE,
5455 "glBindUniformLocationCHROMIUM", "location out of range");
5456 return;
5458 Program* program = GetProgramInfoNotShader(
5459 program_id, "glBindUniformLocationCHROMIUM");
5460 if (!program) {
5461 return;
5463 if (!program->SetUniformLocationBinding(name, location)) {
5464 LOCAL_SET_GL_ERROR(
5465 GL_INVALID_VALUE,
5466 "glBindUniformLocationCHROMIUM", "location out of range");
5470 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5471 uint32 immediate_data_size,
5472 const void* cmd_data) {
5473 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5474 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5475 cmd_data);
5476 GLuint program = static_cast<GLuint>(c.program);
5477 GLint location = static_cast<GLint>(c.location);
5478 Bucket* bucket = GetBucket(c.name_bucket_id);
5479 if (!bucket || bucket->size() == 0) {
5480 return error::kInvalidArguments;
5482 std::string name_str;
5483 if (!bucket->GetAsString(&name_str)) {
5484 return error::kInvalidArguments;
5486 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5487 return error::kNoError;
5490 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5491 const void* cmd_data) {
5492 const gles2::cmds::DeleteShader& c =
5493 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5494 GLuint client_id = c.shader;
5495 if (client_id) {
5496 Shader* shader = GetShader(client_id);
5497 if (shader) {
5498 if (!shader->IsDeleted()) {
5499 shader_manager()->Delete(shader);
5501 } else {
5502 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5505 return error::kNoError;
5508 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5509 const void* cmd_data) {
5510 const gles2::cmds::DeleteProgram& c =
5511 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5512 GLuint client_id = c.program;
5513 if (client_id) {
5514 Program* program = GetProgram(client_id);
5515 if (program) {
5516 if (!program->IsDeleted()) {
5517 program_manager()->MarkAsDeleted(shader_manager(), program);
5519 } else {
5520 LOCAL_SET_GL_ERROR(
5521 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5524 return error::kNoError;
5527 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5528 DCHECK(!ShouldDeferDraws());
5529 if (CheckBoundFramebuffersValid("glClear")) {
5530 ApplyDirtyState();
5531 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5532 if (workarounds().gl_clear_broken) {
5533 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5534 GetErrorState());
5535 if (!BoundFramebufferHasDepthAttachment())
5536 mask &= ~GL_DEPTH_BUFFER_BIT;
5537 if (!BoundFramebufferHasStencilAttachment())
5538 mask &= ~GL_STENCIL_BUFFER_BIT;
5539 clear_framebuffer_blit_->ClearFramebuffer(
5540 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5541 state_.color_clear_green, state_.color_clear_blue,
5542 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5543 return error::kNoError;
5545 glClear(mask);
5547 return error::kNoError;
5550 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5551 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5552 GLuint client_renderbuffer_id) {
5553 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5554 if (!framebuffer) {
5555 LOCAL_SET_GL_ERROR(
5556 GL_INVALID_OPERATION,
5557 "glFramebufferRenderbuffer", "no framebuffer bound");
5558 return;
5560 GLuint service_id = 0;
5561 Renderbuffer* renderbuffer = NULL;
5562 if (client_renderbuffer_id) {
5563 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5564 if (!renderbuffer) {
5565 LOCAL_SET_GL_ERROR(
5566 GL_INVALID_OPERATION,
5567 "glFramebufferRenderbuffer", "unknown renderbuffer");
5568 return;
5570 service_id = renderbuffer->service_id();
5572 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5573 glFramebufferRenderbufferEXT(
5574 target, attachment, renderbuffertarget, service_id);
5575 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5576 if (error == GL_NO_ERROR) {
5577 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5579 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5580 framebuffer_state_.clear_state_dirty = true;
5582 OnFboChanged();
5585 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5586 if (SetCapabilityState(cap, false)) {
5587 glDisable(cap);
5591 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5592 if (SetCapabilityState(cap, true)) {
5593 glEnable(cap);
5597 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5598 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5599 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5600 glDepthRange(znear, zfar);
5603 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5604 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5605 state_.sample_coverage_invert = (invert != 0);
5606 glSampleCoverage(state_.sample_coverage_value, invert);
5609 // Assumes framebuffer is complete.
5610 void GLES2DecoderImpl::ClearUnclearedAttachments(
5611 GLenum target, Framebuffer* framebuffer) {
5612 if (target == GL_READ_FRAMEBUFFER_EXT) {
5613 // bind this to the DRAW point, clear then bind back to READ
5614 // TODO(gman): I don't think there is any guarantee that an FBO that
5615 // is complete on the READ attachment will be complete as a DRAW
5616 // attachment.
5617 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5618 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5620 GLbitfield clear_bits = 0;
5621 if (framebuffer->HasUnclearedColorAttachments()) {
5622 glClearColor(
5623 0.0f, 0.0f, 0.0f,
5624 (GLES2Util::GetChannelsForFormat(
5625 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5626 1.0f);
5627 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5628 clear_bits |= GL_COLOR_BUFFER_BIT;
5629 if (feature_info_->feature_flags().ext_draw_buffers)
5630 framebuffer->PrepareDrawBuffersForClear();
5633 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5634 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5635 glClearStencil(0);
5636 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5637 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5638 clear_bits |= GL_STENCIL_BUFFER_BIT;
5641 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5642 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5643 glClearDepth(1.0f);
5644 state_.SetDeviceDepthMask(GL_TRUE);
5645 clear_bits |= GL_DEPTH_BUFFER_BIT;
5648 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5649 glClear(clear_bits);
5651 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5652 feature_info_->feature_flags().ext_draw_buffers)
5653 framebuffer->RestoreDrawBuffersAfterClear();
5655 framebuffer_manager()->MarkAttachmentsAsCleared(
5656 framebuffer, renderbuffer_manager(), texture_manager());
5658 RestoreClearState();
5660 if (target == GL_READ_FRAMEBUFFER_EXT) {
5661 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5662 Framebuffer* draw_framebuffer =
5663 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5664 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5665 GetBackbufferServiceId();
5666 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5670 void GLES2DecoderImpl::RestoreClearState() {
5671 framebuffer_state_.clear_state_dirty = true;
5672 glClearColor(
5673 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5674 state_.color_clear_alpha);
5675 glClearStencil(state_.stencil_clear);
5676 glClearDepth(state_.depth_clear);
5677 if (state_.enable_flags.scissor_test) {
5678 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5682 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5683 Framebuffer* framebuffer =
5684 GetFramebufferInfoForTarget(target);
5685 if (!framebuffer) {
5686 return GL_FRAMEBUFFER_COMPLETE;
5688 GLenum completeness = framebuffer->IsPossiblyComplete();
5689 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5690 return completeness;
5692 return framebuffer->GetStatus(texture_manager(), target);
5695 void GLES2DecoderImpl::DoFramebufferTexture2D(
5696 GLenum target, GLenum attachment, GLenum textarget,
5697 GLuint client_texture_id, GLint level) {
5698 DoFramebufferTexture2DCommon(
5699 "glFramebufferTexture2D", target, attachment,
5700 textarget, client_texture_id, level, 0);
5703 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5704 GLenum target, GLenum attachment, GLenum textarget,
5705 GLuint client_texture_id, GLint level, GLsizei samples) {
5706 DoFramebufferTexture2DCommon(
5707 "glFramebufferTexture2DMultisample", target, attachment,
5708 textarget, client_texture_id, level, samples);
5711 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5712 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5713 GLuint client_texture_id, GLint level, GLsizei samples) {
5714 if (samples > renderbuffer_manager()->max_samples()) {
5715 LOCAL_SET_GL_ERROR(
5716 GL_INVALID_VALUE,
5717 "glFramebufferTexture2DMultisample", "samples too large");
5718 return;
5720 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5721 if (!framebuffer) {
5722 LOCAL_SET_GL_ERROR(
5723 GL_INVALID_OPERATION,
5724 name, "no framebuffer bound.");
5725 return;
5727 GLuint service_id = 0;
5728 TextureRef* texture_ref = NULL;
5729 if (client_texture_id) {
5730 texture_ref = GetTexture(client_texture_id);
5731 if (!texture_ref) {
5732 LOCAL_SET_GL_ERROR(
5733 GL_INVALID_OPERATION,
5734 name, "unknown texture_ref");
5735 return;
5737 service_id = texture_ref->service_id();
5740 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5741 LOCAL_SET_GL_ERROR(
5742 GL_INVALID_VALUE,
5743 name, "level out of range");
5744 return;
5747 if (texture_ref)
5748 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5750 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5751 if (0 == samples) {
5752 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5753 } else {
5754 if (features().use_img_for_multisampled_render_to_texture) {
5755 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5756 service_id, level, samples);
5757 } else {
5758 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5759 service_id, level, samples);
5762 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5763 if (error == GL_NO_ERROR) {
5764 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5765 samples);
5767 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5768 framebuffer_state_.clear_state_dirty = true;
5771 if (texture_ref)
5772 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5774 OnFboChanged();
5777 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5778 GLenum target, GLenum attachment, GLuint client_texture_id,
5779 GLint level, GLint layer) {
5780 // TODO(zmo): Unsafe ES3 API, missing states update.
5781 GLuint service_id = 0;
5782 TextureRef* texture_ref = NULL;
5783 if (client_texture_id) {
5784 texture_ref = GetTexture(client_texture_id);
5785 if (!texture_ref) {
5786 LOCAL_SET_GL_ERROR(
5787 GL_INVALID_OPERATION,
5788 "glFramebufferTextureLayer", "unknown texture_ref");
5789 return;
5791 service_id = texture_ref->service_id();
5793 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5796 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5797 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5798 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5799 if (!framebuffer) {
5800 LOCAL_SET_GL_ERROR(
5801 GL_INVALID_OPERATION,
5802 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5803 return;
5805 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5806 const Framebuffer::Attachment* attachment_object =
5807 framebuffer->GetAttachment(attachment);
5808 *params = attachment_object ? attachment_object->object_name() : 0;
5809 } else {
5810 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5811 features().use_img_for_multisampled_render_to_texture) {
5812 pname = GL_TEXTURE_SAMPLES_IMG;
5814 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5818 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5819 GLenum target, GLenum pname, GLint* params) {
5820 Renderbuffer* renderbuffer =
5821 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5822 if (!renderbuffer) {
5823 LOCAL_SET_GL_ERROR(
5824 GL_INVALID_OPERATION,
5825 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5826 return;
5829 EnsureRenderbufferBound();
5830 switch (pname) {
5831 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5832 *params = renderbuffer->internal_format();
5833 break;
5834 case GL_RENDERBUFFER_WIDTH:
5835 *params = renderbuffer->width();
5836 break;
5837 case GL_RENDERBUFFER_HEIGHT:
5838 *params = renderbuffer->height();
5839 break;
5840 case GL_RENDERBUFFER_SAMPLES_EXT:
5841 if (features().use_img_for_multisampled_render_to_texture) {
5842 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5843 params);
5844 } else {
5845 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5846 params);
5848 default:
5849 glGetRenderbufferParameterivEXT(target, pname, params);
5850 break;
5854 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5855 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5856 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5857 GLbitfield mask, GLenum filter) {
5858 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5860 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5861 return;
5864 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5865 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5866 BlitFramebufferHelper(
5867 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5868 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5869 state_.enable_flags.scissor_test);
5872 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5873 if (!state_.bound_renderbuffer_valid) {
5874 state_.bound_renderbuffer_valid = true;
5875 glBindRenderbufferEXT(GL_RENDERBUFFER,
5876 state_.bound_renderbuffer.get()
5877 ? state_.bound_renderbuffer->service_id()
5878 : 0);
5882 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5883 const FeatureInfo* feature_info,
5884 GLenum target,
5885 GLsizei samples,
5886 GLenum internal_format,
5887 GLsizei width,
5888 GLsizei height) {
5889 // TODO(sievers): This could be resolved at the GL binding level, but the
5890 // binding process is currently a bit too 'brute force'.
5891 if (feature_info->gl_version_info().is_angle) {
5892 glRenderbufferStorageMultisampleANGLE(
5893 target, samples, internal_format, width, height);
5894 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5895 glRenderbufferStorageMultisample(
5896 target, samples, internal_format, width, height);
5897 } else {
5898 glRenderbufferStorageMultisampleEXT(
5899 target, samples, internal_format, width, height);
5903 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5904 GLint srcY0,
5905 GLint srcX1,
5906 GLint srcY1,
5907 GLint dstX0,
5908 GLint dstY0,
5909 GLint dstX1,
5910 GLint dstY1,
5911 GLbitfield mask,
5912 GLenum filter) {
5913 // TODO(sievers): This could be resolved at the GL binding level, but the
5914 // binding process is currently a bit too 'brute force'.
5915 if (feature_info_->gl_version_info().is_angle) {
5916 glBlitFramebufferANGLE(
5917 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5918 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5919 glBlitFramebuffer(
5920 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5921 } else {
5922 glBlitFramebufferEXT(
5923 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5927 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5928 GLsizei samples,
5929 GLenum internalformat,
5930 GLsizei width,
5931 GLsizei height) {
5932 if (samples > renderbuffer_manager()->max_samples()) {
5933 LOCAL_SET_GL_ERROR(
5934 GL_INVALID_VALUE,
5935 "glRenderbufferStorageMultisample", "samples too large");
5936 return false;
5939 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5940 height > renderbuffer_manager()->max_renderbuffer_size()) {
5941 LOCAL_SET_GL_ERROR(
5942 GL_INVALID_VALUE,
5943 "glRenderbufferStorageMultisample", "dimensions too large");
5944 return false;
5947 uint32 estimated_size = 0;
5948 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5949 width, height, samples, internalformat, &estimated_size)) {
5950 LOCAL_SET_GL_ERROR(
5951 GL_OUT_OF_MEMORY,
5952 "glRenderbufferStorageMultisample", "dimensions too large");
5953 return false;
5956 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5957 LOCAL_SET_GL_ERROR(
5958 GL_OUT_OF_MEMORY,
5959 "glRenderbufferStorageMultisample", "out of memory");
5960 return false;
5963 return true;
5966 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5967 GLenum target, GLsizei samples, GLenum internalformat,
5968 GLsizei width, GLsizei height) {
5969 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5970 if (!renderbuffer) {
5971 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5972 "glRenderbufferStorageMultisampleCHROMIUM",
5973 "no renderbuffer bound");
5974 return;
5977 if (!ValidateRenderbufferStorageMultisample(
5978 samples, internalformat, width, height)) {
5979 return;
5982 EnsureRenderbufferBound();
5983 GLenum impl_format =
5984 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5985 internalformat);
5986 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5987 "glRenderbufferStorageMultisampleCHROMIUM");
5988 RenderbufferStorageMultisampleHelper(
5989 feature_info_.get(), target, samples, impl_format, width, height);
5990 GLenum error =
5991 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5992 if (error == GL_NO_ERROR) {
5993 if (workarounds().validate_multisample_buffer_allocation) {
5994 if (!VerifyMultisampleRenderbufferIntegrity(
5995 renderbuffer->service_id(), impl_format)) {
5996 LOCAL_SET_GL_ERROR(
5997 GL_OUT_OF_MEMORY,
5998 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5999 return;
6003 // TODO(gman): If renderbuffers tracked which framebuffers they were
6004 // attached to we could just mark those framebuffers as not complete.
6005 framebuffer_manager()->IncFramebufferStateChangeCount();
6006 renderbuffer_manager()->SetInfo(
6007 renderbuffer, samples, internalformat, width, height);
6011 // This is the handler for multisampled_render_to_texture extensions.
6012 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6013 GLenum target, GLsizei samples, GLenum internalformat,
6014 GLsizei width, GLsizei height) {
6015 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6016 if (!renderbuffer) {
6017 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6018 "glRenderbufferStorageMultisampleEXT",
6019 "no renderbuffer bound");
6020 return;
6023 if (!ValidateRenderbufferStorageMultisample(
6024 samples, internalformat, width, height)) {
6025 return;
6028 EnsureRenderbufferBound();
6029 GLenum impl_format =
6030 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6031 internalformat);
6032 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6033 if (features().use_img_for_multisampled_render_to_texture) {
6034 glRenderbufferStorageMultisampleIMG(
6035 target, samples, impl_format, width, height);
6036 } else {
6037 glRenderbufferStorageMultisampleEXT(
6038 target, samples, impl_format, width, height);
6040 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6041 if (error == GL_NO_ERROR) {
6042 // TODO(gman): If renderbuffers tracked which framebuffers they were
6043 // attached to we could just mark those framebuffers as not complete.
6044 framebuffer_manager()->IncFramebufferStateChangeCount();
6045 renderbuffer_manager()->SetInfo(
6046 renderbuffer, samples, internalformat, width, height);
6050 // This function validates the allocation of a multisampled renderbuffer
6051 // by clearing it to a key color, blitting the contents to a texture, and
6052 // reading back the color to ensure it matches the key.
6053 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6054 GLuint renderbuffer, GLenum format) {
6056 // Only validate color buffers.
6057 // These formats have been selected because they are very common or are known
6058 // to be used by the WebGL backbuffer. If problems are observed with other
6059 // color formats they can be added here.
6060 switch (format) {
6061 case GL_RGB:
6062 case GL_RGB8:
6063 case GL_RGBA:
6064 case GL_RGBA8:
6065 break;
6066 default:
6067 return true;
6070 GLint draw_framebuffer, read_framebuffer;
6072 // Cache framebuffer and texture bindings.
6073 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6074 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6076 if (!validation_texture_) {
6077 GLint bound_texture;
6078 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6080 // Create additional resources needed for the verification.
6081 glGenTextures(1, &validation_texture_);
6082 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6083 glGenFramebuffersEXT(1, &validation_fbo_);
6085 // Texture only needs to be 1x1.
6086 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6087 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6088 // multisample will fail if the color format of the source and destination
6089 // do not match. Here, we assume that the source is GL_RGBA, and make the
6090 // destination GL_RGBA. http://crbug.com/484203
6091 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6092 GL_UNSIGNED_BYTE, NULL);
6094 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6095 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6096 GL_TEXTURE_2D, validation_texture_, 0);
6098 glBindTexture(GL_TEXTURE_2D, bound_texture);
6101 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6102 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6103 GL_RENDERBUFFER, renderbuffer);
6105 // Cache current state and reset it to the values we require.
6106 GLboolean scissor_enabled = false;
6107 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6108 if (scissor_enabled)
6109 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6111 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6112 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6113 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6115 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6116 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6117 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6119 // Clear the buffer to the desired key color.
6120 glClear(GL_COLOR_BUFFER_BIT);
6122 // Blit from the multisample buffer to a standard texture.
6123 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6124 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6126 BlitFramebufferHelper(
6127 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6129 // Read a pixel from the buffer.
6130 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6132 unsigned char pixel[3] = {0, 0, 0};
6133 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6135 // Detach the renderbuffer.
6136 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6137 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6138 GL_RENDERBUFFER, 0);
6140 // Restore cached state.
6141 if (scissor_enabled)
6142 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6144 state_.SetDeviceColorMask(
6145 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6146 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6147 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6148 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6150 // Return true if the pixel matched the desired key color.
6151 return (pixel[0] == 0xFF &&
6152 pixel[1] == 0x00 &&
6153 pixel[2] == 0xFF);
6156 void GLES2DecoderImpl::DoRenderbufferStorage(
6157 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6158 Renderbuffer* renderbuffer =
6159 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6160 if (!renderbuffer) {
6161 LOCAL_SET_GL_ERROR(
6162 GL_INVALID_OPERATION,
6163 "glRenderbufferStorage", "no renderbuffer bound");
6164 return;
6167 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6168 height > renderbuffer_manager()->max_renderbuffer_size()) {
6169 LOCAL_SET_GL_ERROR(
6170 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6171 return;
6174 uint32 estimated_size = 0;
6175 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6176 width, height, 1, internalformat, &estimated_size)) {
6177 LOCAL_SET_GL_ERROR(
6178 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6179 return;
6182 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6183 LOCAL_SET_GL_ERROR(
6184 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6185 return;
6188 EnsureRenderbufferBound();
6189 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6190 glRenderbufferStorageEXT(
6191 target,
6192 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6193 internalformat),
6194 width,
6195 height);
6196 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6197 if (error == GL_NO_ERROR) {
6198 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6199 // we could just mark those framebuffers as not complete.
6200 framebuffer_manager()->IncFramebufferStateChangeCount();
6201 renderbuffer_manager()->SetInfo(
6202 renderbuffer, 1, internalformat, width, height);
6206 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6207 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6208 Program* program = GetProgramInfoNotShader(
6209 program_id, "glLinkProgram");
6210 if (!program) {
6211 return;
6214 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6215 if (program->Link(shader_manager(),
6216 workarounds().count_all_in_varyings_packing ?
6217 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6218 shader_cache_callback_)) {
6219 if (program == state_.current_program.get()) {
6220 if (workarounds().use_current_program_after_successful_link)
6221 glUseProgram(program->service_id());
6222 if (workarounds().clear_uniforms_before_first_program_use)
6223 program_manager()->ClearUniforms(program);
6227 // LinkProgram can be very slow. Exit command processing to allow for
6228 // context preemption and GPU watchdog checks.
6229 ExitCommandProcessingEarly();
6232 void GLES2DecoderImpl::DoSamplerParameterfv(
6233 GLuint sampler, GLenum pname, const GLfloat* params) {
6234 DCHECK(params);
6235 glSamplerParameterf(sampler, pname, params[0]);
6238 void GLES2DecoderImpl::DoSamplerParameteriv(
6239 GLuint sampler, GLenum pname, const GLint* params) {
6240 DCHECK(params);
6241 glSamplerParameteri(sampler, pname, params[0]);
6244 void GLES2DecoderImpl::DoTexParameterf(
6245 GLenum target, GLenum pname, GLfloat param) {
6246 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6247 &state_, target);
6248 if (!texture) {
6249 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6250 return;
6253 texture_manager()->SetParameterf(
6254 "glTexParameterf", GetErrorState(), texture, pname, param);
6257 void GLES2DecoderImpl::DoTexParameteri(
6258 GLenum target, GLenum pname, GLint param) {
6259 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6260 &state_, target);
6261 if (!texture) {
6262 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6263 return;
6266 texture_manager()->SetParameteri(
6267 "glTexParameteri", GetErrorState(), texture, pname, param);
6270 void GLES2DecoderImpl::DoTexParameterfv(
6271 GLenum target, GLenum pname, const GLfloat* params) {
6272 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6273 &state_, target);
6274 if (!texture) {
6275 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6276 return;
6279 texture_manager()->SetParameterf(
6280 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6283 void GLES2DecoderImpl::DoTexParameteriv(
6284 GLenum target, GLenum pname, const GLint* params) {
6285 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6286 &state_, target);
6287 if (!texture) {
6288 LOCAL_SET_GL_ERROR(
6289 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6290 return;
6293 texture_manager()->SetParameteri(
6294 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6297 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6298 if (!state_.bound_valuebuffer.get()) {
6299 // There is no valuebuffer bound
6300 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6301 "no valuebuffer in use");
6302 return false;
6304 return true;
6307 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6308 GLenum subscription,
6309 const char* function_name) {
6310 if (!CheckCurrentValuebuffer(function_name)) {
6311 return false;
6313 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6314 // The valuebuffer is not subscribed to the target
6315 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6316 "valuebuffer is not subscribed");
6317 return false;
6319 return true;
6322 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6323 GLenum subscription,
6324 const char* function_name) {
6325 if (!CheckCurrentProgramForUniform(location, function_name)) {
6326 return false;
6328 GLint real_location = -1;
6329 GLint array_index = -1;
6330 const Program::UniformInfo* info =
6331 state_.current_program->GetUniformInfoByFakeLocation(
6332 location, &real_location, &array_index);
6333 if (!info) {
6334 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6335 return false;
6337 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6338 info->accepts_api_type) == 0) {
6339 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6340 "wrong type for subscription");
6341 return false;
6343 return true;
6346 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6347 if (!state_.current_program.get()) {
6348 // The program does not exist.
6349 LOCAL_SET_GL_ERROR(
6350 GL_INVALID_OPERATION, function_name, "no program in use");
6351 return false;
6353 if (!state_.current_program->InUse()) {
6354 LOCAL_SET_GL_ERROR(
6355 GL_INVALID_OPERATION, function_name, "program not linked");
6356 return false;
6358 return true;
6361 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6362 GLint location, const char* function_name) {
6363 if (!CheckCurrentProgram(function_name)) {
6364 return false;
6366 return location != -1;
6369 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6370 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6371 if (!framebuffer)
6372 return false;
6373 const Framebuffer::Attachment* attachment =
6374 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6375 if (!attachment)
6376 return false;
6378 DCHECK(state_.current_program.get());
6379 const Program::SamplerIndices& sampler_indices =
6380 state_.current_program->sampler_indices();
6381 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6382 const Program::UniformInfo* uniform_info =
6383 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6384 DCHECK(uniform_info);
6385 if (uniform_info->type != GL_SAMPLER_2D)
6386 continue;
6387 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6388 GLuint texture_unit_index = uniform_info->texture_units[jj];
6389 if (texture_unit_index >= state_.texture_units.size())
6390 continue;
6391 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6392 TextureRef* texture_ref =
6393 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6394 if (attachment->IsTexture(texture_ref))
6395 return true;
6398 return false;
6401 bool GLES2DecoderImpl::CheckUniformForApiType(
6402 const Program::UniformInfo* info,
6403 const char* function_name,
6404 Program::UniformApiType api_type) {
6405 DCHECK(info);
6406 if ((api_type & info->accepts_api_type) == 0) {
6407 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6408 "wrong uniform function for type");
6409 return false;
6411 return true;
6414 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6415 GLint fake_location,
6416 const char* function_name,
6417 Program::UniformApiType api_type,
6418 GLint* real_location,
6419 GLenum* type,
6420 GLsizei* count) {
6421 DCHECK(type);
6422 DCHECK(count);
6423 DCHECK(real_location);
6425 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6426 return false;
6428 GLint array_index = -1;
6429 const Program::UniformInfo* info =
6430 state_.current_program->GetUniformInfoByFakeLocation(
6431 fake_location, real_location, &array_index);
6432 if (!info) {
6433 LOCAL_SET_GL_ERROR(
6434 GL_INVALID_OPERATION, function_name, "unknown location");
6435 return false;
6437 if (!CheckUniformForApiType(info, function_name, api_type)) {
6438 return false;
6440 if (*count > 1 && !info->is_array) {
6441 LOCAL_SET_GL_ERROR(
6442 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6443 return false;
6445 *count = std::min(info->size - array_index, *count);
6446 if (*count <= 0) {
6447 return false;
6449 *type = info->type;
6450 return true;
6453 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6454 GLenum type = 0;
6455 GLsizei count = 1;
6456 GLint real_location = -1;
6457 if (!PrepForSetUniformByLocation(fake_location,
6458 "glUniform1i",
6459 Program::kUniform1i,
6460 &real_location,
6461 &type,
6462 &count)) {
6463 return;
6465 if (!state_.current_program->SetSamplers(
6466 state_.texture_units.size(), fake_location, 1, &v0)) {
6467 LOCAL_SET_GL_ERROR(
6468 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6469 return;
6471 glUniform1i(real_location, v0);
6474 void GLES2DecoderImpl::DoUniform1iv(
6475 GLint fake_location, GLsizei count, const GLint *value) {
6476 GLenum type = 0;
6477 GLint real_location = -1;
6478 if (!PrepForSetUniformByLocation(fake_location,
6479 "glUniform1iv",
6480 Program::kUniform1i,
6481 &real_location,
6482 &type,
6483 &count)) {
6484 return;
6486 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6487 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6488 if (!state_.current_program->SetSamplers(
6489 state_.texture_units.size(), fake_location, count, value)) {
6490 LOCAL_SET_GL_ERROR(
6491 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6492 return;
6495 glUniform1iv(real_location, count, value);
6498 void GLES2DecoderImpl::DoUniform1fv(
6499 GLint fake_location, GLsizei count, const GLfloat* value) {
6500 GLenum type = 0;
6501 GLint real_location = -1;
6502 if (!PrepForSetUniformByLocation(fake_location,
6503 "glUniform1fv",
6504 Program::kUniform1f,
6505 &real_location,
6506 &type,
6507 &count)) {
6508 return;
6510 if (type == GL_BOOL) {
6511 scoped_ptr<GLint[]> temp(new GLint[count]);
6512 for (GLsizei ii = 0; ii < count; ++ii) {
6513 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6515 DoUniform1iv(real_location, count, temp.get());
6516 } else {
6517 glUniform1fv(real_location, count, value);
6521 void GLES2DecoderImpl::DoUniform2fv(
6522 GLint fake_location, GLsizei count, const GLfloat* value) {
6523 GLenum type = 0;
6524 GLint real_location = -1;
6525 if (!PrepForSetUniformByLocation(fake_location,
6526 "glUniform2fv",
6527 Program::kUniform2f,
6528 &real_location,
6529 &type,
6530 &count)) {
6531 return;
6533 if (type == GL_BOOL_VEC2) {
6534 GLsizei num_values = count * 2;
6535 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6536 for (GLsizei ii = 0; ii < num_values; ++ii) {
6537 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6539 glUniform2iv(real_location, count, temp.get());
6540 } else {
6541 glUniform2fv(real_location, count, value);
6545 void GLES2DecoderImpl::DoUniform3fv(
6546 GLint fake_location, GLsizei count, const GLfloat* value) {
6547 GLenum type = 0;
6548 GLint real_location = -1;
6549 if (!PrepForSetUniformByLocation(fake_location,
6550 "glUniform3fv",
6551 Program::kUniform3f,
6552 &real_location,
6553 &type,
6554 &count)) {
6555 return;
6557 if (type == GL_BOOL_VEC3) {
6558 GLsizei num_values = count * 3;
6559 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6560 for (GLsizei ii = 0; ii < num_values; ++ii) {
6561 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6563 glUniform3iv(real_location, count, temp.get());
6564 } else {
6565 glUniform3fv(real_location, count, value);
6569 void GLES2DecoderImpl::DoUniform4fv(
6570 GLint fake_location, GLsizei count, const GLfloat* value) {
6571 GLenum type = 0;
6572 GLint real_location = -1;
6573 if (!PrepForSetUniformByLocation(fake_location,
6574 "glUniform4fv",
6575 Program::kUniform4f,
6576 &real_location,
6577 &type,
6578 &count)) {
6579 return;
6581 if (type == GL_BOOL_VEC4) {
6582 GLsizei num_values = count * 4;
6583 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6584 for (GLsizei ii = 0; ii < num_values; ++ii) {
6585 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6587 glUniform4iv(real_location, count, temp.get());
6588 } else {
6589 glUniform4fv(real_location, count, value);
6593 void GLES2DecoderImpl::DoUniform2iv(
6594 GLint fake_location, GLsizei count, const GLint* value) {
6595 GLenum type = 0;
6596 GLint real_location = -1;
6597 if (!PrepForSetUniformByLocation(fake_location,
6598 "glUniform2iv",
6599 Program::kUniform2i,
6600 &real_location,
6601 &type,
6602 &count)) {
6603 return;
6605 glUniform2iv(real_location, count, value);
6608 void GLES2DecoderImpl::DoUniform3iv(
6609 GLint fake_location, GLsizei count, const GLint* value) {
6610 GLenum type = 0;
6611 GLint real_location = -1;
6612 if (!PrepForSetUniformByLocation(fake_location,
6613 "glUniform3iv",
6614 Program::kUniform3i,
6615 &real_location,
6616 &type,
6617 &count)) {
6618 return;
6620 glUniform3iv(real_location, count, value);
6623 void GLES2DecoderImpl::DoUniform4iv(
6624 GLint fake_location, GLsizei count, const GLint* value) {
6625 GLenum type = 0;
6626 GLint real_location = -1;
6627 if (!PrepForSetUniformByLocation(fake_location,
6628 "glUniform4iv",
6629 Program::kUniform4i,
6630 &real_location,
6631 &type,
6632 &count)) {
6633 return;
6635 glUniform4iv(real_location, count, value);
6638 void GLES2DecoderImpl::DoUniformMatrix2fv(
6639 GLint fake_location, GLsizei count, GLboolean transpose,
6640 const GLfloat* value) {
6641 GLenum type = 0;
6642 GLint real_location = -1;
6643 if (!PrepForSetUniformByLocation(fake_location,
6644 "glUniformMatrix2fv",
6645 Program::kUniformMatrix2f,
6646 &real_location,
6647 &type,
6648 &count)) {
6649 return;
6651 glUniformMatrix2fv(real_location, count, transpose, value);
6654 void GLES2DecoderImpl::DoUniformMatrix3fv(
6655 GLint fake_location, GLsizei count, GLboolean transpose,
6656 const GLfloat* value) {
6657 GLenum type = 0;
6658 GLint real_location = -1;
6659 if (!PrepForSetUniformByLocation(fake_location,
6660 "glUniformMatrix3fv",
6661 Program::kUniformMatrix3f,
6662 &real_location,
6663 &type,
6664 &count)) {
6665 return;
6667 glUniformMatrix3fv(real_location, count, transpose, value);
6670 void GLES2DecoderImpl::DoUniformMatrix4fv(
6671 GLint fake_location, GLsizei count, GLboolean transpose,
6672 const GLfloat* value) {
6673 GLenum type = 0;
6674 GLint real_location = -1;
6675 if (!PrepForSetUniformByLocation(fake_location,
6676 "glUniformMatrix4fv",
6677 Program::kUniformMatrix4f,
6678 &real_location,
6679 &type,
6680 &count)) {
6681 return;
6683 glUniformMatrix4fv(real_location, count, transpose, value);
6686 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6687 GLuint service_id = 0;
6688 Program* program = NULL;
6689 if (program_id) {
6690 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6691 if (!program) {
6692 return;
6694 if (!program->IsValid()) {
6695 // Program was not linked successfully. (ie, glLinkProgram)
6696 LOCAL_SET_GL_ERROR(
6697 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6698 return;
6700 service_id = program->service_id();
6702 if (state_.current_program.get()) {
6703 program_manager()->UnuseProgram(shader_manager(),
6704 state_.current_program.get());
6706 state_.current_program = program;
6707 LogClientServiceMapping("glUseProgram", program_id, service_id);
6708 glUseProgram(service_id);
6709 if (state_.current_program.get()) {
6710 program_manager()->UseProgram(state_.current_program.get());
6711 if (workarounds().clear_uniforms_before_first_program_use)
6712 program_manager()->ClearUniforms(program);
6716 void GLES2DecoderImpl::RenderWarning(
6717 const char* filename, int line, const std::string& msg) {
6718 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6721 void GLES2DecoderImpl::PerformanceWarning(
6722 const char* filename, int line, const std::string& msg) {
6723 logger_.LogMessage(filename, line,
6724 std::string("PERFORMANCE WARNING: ") + msg);
6727 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6728 Texture* texture, GLenum textarget) {
6729 // Image is already in use if texture is attached to a framebuffer.
6730 if (texture && !texture->IsAttachedToFramebuffer()) {
6731 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6732 if (image) {
6733 ScopedGLErrorSuppressor suppressor(
6734 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6735 GetErrorState());
6736 glBindTexture(textarget, texture->service_id());
6737 image->WillUseTexImage();
6738 RestoreCurrentTextureBindings(&state_, textarget);
6743 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6744 Texture* texture, GLenum textarget) {
6745 // Image is still in use if texture is attached to a framebuffer.
6746 if (texture && !texture->IsAttachedToFramebuffer()) {
6747 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6748 if (image) {
6749 ScopedGLErrorSuppressor suppressor(
6750 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6751 GetErrorState());
6752 glBindTexture(textarget, texture->service_id());
6753 image->DidUseTexImage();
6754 RestoreCurrentTextureBindings(&state_, textarget);
6759 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6760 DCHECK(state_.current_program.get());
6761 if (!texture_manager()->HaveUnrenderableTextures() &&
6762 !texture_manager()->HaveImages()) {
6763 return true;
6766 bool textures_set = false;
6767 const Program::SamplerIndices& sampler_indices =
6768 state_.current_program->sampler_indices();
6769 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6770 const Program::UniformInfo* uniform_info =
6771 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6772 DCHECK(uniform_info);
6773 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6774 GLuint texture_unit_index = uniform_info->texture_units[jj];
6775 if (texture_unit_index < state_.texture_units.size()) {
6776 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6777 TextureRef* texture_ref =
6778 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6779 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6780 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6781 textures_set = true;
6782 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6783 glBindTexture(
6784 textarget,
6785 texture_manager()->black_texture_id(uniform_info->type));
6786 if (!texture_ref) {
6787 LOCAL_RENDER_WARNING(
6788 std::string("there is no texture bound to the unit ") +
6789 base::IntToString(texture_unit_index));
6790 } else {
6791 LOCAL_RENDER_WARNING(
6792 std::string("texture bound to texture unit ") +
6793 base::IntToString(texture_unit_index) +
6794 " is not renderable. It maybe non-power-of-2 and have"
6795 " incompatible texture filtering.");
6797 continue;
6800 if (textarget != GL_TEXTURE_CUBE_MAP) {
6801 Texture* texture = texture_ref->texture();
6802 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6803 if (image && !texture->IsAttachedToFramebuffer()) {
6804 ScopedGLErrorSuppressor suppressor(
6805 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6806 textures_set = true;
6807 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6808 image->WillUseTexImage();
6809 continue;
6813 // else: should this be an error?
6816 return !textures_set;
6819 void GLES2DecoderImpl::RestoreStateForTextures() {
6820 DCHECK(state_.current_program.get());
6821 const Program::SamplerIndices& sampler_indices =
6822 state_.current_program->sampler_indices();
6823 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6824 const Program::UniformInfo* uniform_info =
6825 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6826 DCHECK(uniform_info);
6827 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6828 GLuint texture_unit_index = uniform_info->texture_units[jj];
6829 if (texture_unit_index < state_.texture_units.size()) {
6830 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6831 TextureRef* texture_ref =
6832 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6833 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6834 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6835 // Get the texture_ref info that was previously bound here.
6836 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6837 ? texture_unit.bound_texture_2d.get()
6838 : texture_unit.bound_texture_cube_map.get();
6839 glBindTexture(texture_unit.bind_target,
6840 texture_ref ? texture_ref->service_id() : 0);
6841 continue;
6844 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6845 Texture* texture = texture_ref->texture();
6846 gfx::GLImage* image =
6847 texture->GetLevelImage(texture_unit.bind_target, 0);
6848 if (image && !texture->IsAttachedToFramebuffer()) {
6849 ScopedGLErrorSuppressor suppressor(
6850 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6851 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6852 image->DidUseTexImage();
6853 continue;
6859 // Set the active texture back to whatever the user had it as.
6860 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6863 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6864 // Only check if there are some uncleared textures.
6865 if (!texture_manager()->HaveUnsafeTextures()) {
6866 return true;
6869 // 1: Check all textures we are about to render with.
6870 if (state_.current_program.get()) {
6871 const Program::SamplerIndices& sampler_indices =
6872 state_.current_program->sampler_indices();
6873 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6874 const Program::UniformInfo* uniform_info =
6875 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6876 DCHECK(uniform_info);
6877 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6878 GLuint texture_unit_index = uniform_info->texture_units[jj];
6879 if (texture_unit_index < state_.texture_units.size()) {
6880 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6881 TextureRef* texture_ref =
6882 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6883 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6884 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6885 return false;
6892 return true;
6895 bool GLES2DecoderImpl::IsDrawValid(
6896 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6897 GLsizei primcount) {
6898 DCHECK(instanced || primcount == 1);
6900 // NOTE: We specifically do not check current_program->IsValid() because
6901 // it could never be invalid since glUseProgram would have failed. While
6902 // glLinkProgram could later mark the program as invalid the previous
6903 // valid program will still function if it is still the current program.
6904 if (!state_.current_program.get()) {
6905 // The program does not exist.
6906 // But GL says no ERROR.
6907 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6908 return false;
6911 if (CheckDrawingFeedbackLoops()) {
6912 LOCAL_SET_GL_ERROR(
6913 GL_INVALID_OPERATION, function_name,
6914 "Source and destination textures of the draw are the same.");
6915 return false;
6918 return state_.vertex_attrib_manager
6919 ->ValidateBindings(function_name,
6920 this,
6921 feature_info_.get(),
6922 state_.current_program.get(),
6923 max_vertex_accessed,
6924 instanced,
6925 primcount);
6928 bool GLES2DecoderImpl::SimulateAttrib0(
6929 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6930 DCHECK(simulated);
6931 *simulated = false;
6933 if (feature_info_->gl_version_info().BehavesLikeGLES())
6934 return true;
6936 const VertexAttrib* attrib =
6937 state_.vertex_attrib_manager->GetVertexAttrib(0);
6938 // If it's enabled or it's not used then we don't need to do anything.
6939 bool attrib_0_used =
6940 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6941 if (attrib->enabled() && attrib_0_used) {
6942 return true;
6945 // Make a buffer with a single repeated vec4 value enough to
6946 // simulate the constant value that is supposed to be here.
6947 // This is required to emulate GLES2 on GL.
6948 GLuint num_vertices = max_vertex_accessed + 1;
6949 uint32 size_needed = 0;
6951 if (num_vertices == 0 ||
6952 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
6953 size_needed > 0x7FFFFFFFU) {
6954 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6955 return false;
6958 LOCAL_PERFORMANCE_WARNING(
6959 "Attribute 0 is disabled. This has signficant performance penalty");
6961 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6962 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6964 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6965 if (new_buffer) {
6966 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6967 GLenum error = glGetError();
6968 if (error != GL_NO_ERROR) {
6969 LOCAL_SET_GL_ERROR(
6970 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6971 return false;
6975 const Vec4& value = state_.attrib_values[0];
6976 if (new_buffer ||
6977 (attrib_0_used &&
6978 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
6979 // TODO(zmo): This is not 100% correct because we might lose data when
6980 // casting to float type, but it is a corner case and once we migrate to
6981 // core profiles on desktop GL, it is no longer relevant.
6982 Vec4f fvalue(value);
6983 std::vector<Vec4f> temp(num_vertices, fvalue);
6984 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6985 attrib_0_buffer_matches_value_ = true;
6986 attrib_0_value_ = value;
6987 attrib_0_size_ = size_needed;
6990 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6992 if (attrib->divisor())
6993 glVertexAttribDivisorANGLE(0, 0);
6995 *simulated = true;
6996 return true;
6999 void GLES2DecoderImpl::RestoreStateForAttrib(
7000 GLuint attrib_index, bool restore_array_binding) {
7001 const VertexAttrib* attrib =
7002 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7003 if (restore_array_binding) {
7004 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7005 Buffer* buffer = attrib->buffer();
7006 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7007 glVertexAttribPointer(
7008 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7009 attrib->gl_stride(), ptr);
7011 if (attrib->divisor())
7012 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7013 glBindBuffer(
7014 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7015 state_.bound_array_buffer->service_id() : 0);
7017 // Never touch vertex attribute 0's state (in particular, never
7018 // disable it) when running on desktop GL because it will never be
7019 // re-enabled.
7020 if (attrib_index != 0 ||
7021 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7022 if (attrib->enabled()) {
7023 glEnableVertexAttribArray(attrib_index);
7024 } else {
7025 glDisableVertexAttribArray(attrib_index);
7030 bool GLES2DecoderImpl::SimulateFixedAttribs(
7031 const char* function_name,
7032 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7033 DCHECK(simulated);
7034 *simulated = false;
7035 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7036 return true;
7038 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7039 return true;
7042 LOCAL_PERFORMANCE_WARNING(
7043 "GL_FIXED attributes have a signficant performance penalty");
7045 // NOTE: we could be smart and try to check if a buffer is used
7046 // twice in 2 different attribs, find the overlapping parts and therefore
7047 // duplicate the minimum amount of data but this whole code path is not meant
7048 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7049 // tests so we just add to the buffer attrib used.
7051 GLuint elements_needed = 0;
7052 const VertexAttribManager::VertexAttribList& enabled_attribs =
7053 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7054 for (VertexAttribManager::VertexAttribList::const_iterator it =
7055 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7056 const VertexAttrib* attrib = *it;
7057 const Program::VertexAttrib* attrib_info =
7058 state_.current_program->GetAttribInfoByLocation(attrib->index());
7059 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7060 max_vertex_accessed);
7061 GLuint num_vertices = max_accessed + 1;
7062 if (num_vertices == 0) {
7063 LOCAL_SET_GL_ERROR(
7064 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7065 return false;
7067 if (attrib_info &&
7068 attrib->CanAccess(max_accessed) &&
7069 attrib->type() == GL_FIXED) {
7070 uint32 elements_used = 0;
7071 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7072 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7073 LOCAL_SET_GL_ERROR(
7074 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7075 return false;
7080 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7081 uint32 size_needed = 0;
7082 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7083 size_needed > 0x7FFFFFFFU) {
7084 LOCAL_SET_GL_ERROR(
7085 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7086 return false;
7089 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7091 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7092 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7093 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7094 GLenum error = glGetError();
7095 if (error != GL_NO_ERROR) {
7096 LOCAL_SET_GL_ERROR(
7097 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7098 return false;
7102 // Copy the elements and convert to float
7103 GLintptr offset = 0;
7104 for (VertexAttribManager::VertexAttribList::const_iterator it =
7105 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7106 const VertexAttrib* attrib = *it;
7107 const Program::VertexAttrib* attrib_info =
7108 state_.current_program->GetAttribInfoByLocation(attrib->index());
7109 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7110 max_vertex_accessed);
7111 GLuint num_vertices = max_accessed + 1;
7112 if (num_vertices == 0) {
7113 LOCAL_SET_GL_ERROR(
7114 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7115 return false;
7117 if (attrib_info &&
7118 attrib->CanAccess(max_accessed) &&
7119 attrib->type() == GL_FIXED) {
7120 int num_elements = attrib->size() * num_vertices;
7121 const int src_size = num_elements * sizeof(int32);
7122 const int dst_size = num_elements * sizeof(float);
7123 scoped_ptr<float[]> data(new float[num_elements]);
7124 const int32* src = reinterpret_cast<const int32 *>(
7125 attrib->buffer()->GetRange(attrib->offset(), src_size));
7126 const int32* end = src + num_elements;
7127 float* dst = data.get();
7128 while (src != end) {
7129 *dst++ = static_cast<float>(*src++) / 65536.0f;
7131 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7132 glVertexAttribPointer(
7133 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7134 reinterpret_cast<GLvoid*>(offset));
7135 offset += dst_size;
7138 *simulated = true;
7139 return true;
7142 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7143 // There's no need to call glVertexAttribPointer because we shadow all the
7144 // settings and passing GL_FIXED to it will not work.
7145 glBindBuffer(
7146 GL_ARRAY_BUFFER,
7147 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7148 : 0);
7151 error::Error GLES2DecoderImpl::DoDrawArrays(
7152 const char* function_name,
7153 bool instanced,
7154 GLenum mode,
7155 GLint first,
7156 GLsizei count,
7157 GLsizei primcount) {
7158 error::Error error = WillAccessBoundFramebufferForDraw();
7159 if (error != error::kNoError)
7160 return error;
7161 if (!validators_->draw_mode.IsValid(mode)) {
7162 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7163 return error::kNoError;
7165 if (count < 0) {
7166 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7167 return error::kNoError;
7169 if (primcount < 0) {
7170 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7171 return error::kNoError;
7173 if (!CheckBoundFramebuffersValid(function_name)) {
7174 return error::kNoError;
7176 // We have to check this here because the prototype for glDrawArrays
7177 // is GLint not GLsizei.
7178 if (first < 0) {
7179 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7180 return error::kNoError;
7183 if (count == 0 || primcount == 0) {
7184 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7185 return error::kNoError;
7188 GLuint max_vertex_accessed = first + count - 1;
7189 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7190 if (!ClearUnclearedTextures()) {
7191 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7192 return error::kNoError;
7194 bool simulated_attrib_0 = false;
7195 if (!SimulateAttrib0(
7196 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7197 return error::kNoError;
7199 bool simulated_fixed_attribs = false;
7200 if (SimulateFixedAttribs(
7201 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7202 primcount)) {
7203 bool textures_set = !PrepareTexturesForRender();
7204 ApplyDirtyState();
7205 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7206 if (!instanced) {
7207 glDrawArrays(mode, first, count);
7208 } else {
7209 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7211 if (textures_set) {
7212 RestoreStateForTextures();
7214 if (simulated_fixed_attribs) {
7215 RestoreStateForSimulatedFixedAttribs();
7218 if (simulated_attrib_0) {
7219 // We don't have to restore attrib 0 generic data at the end of this
7220 // function even if it is simulated. This is because we will simulate
7221 // it in each draw call, and attrib 0 generic data queries use cached
7222 // values instead of passing down to the underlying driver.
7223 RestoreStateForAttrib(0, false);
7226 return error::kNoError;
7229 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7230 const void* cmd_data) {
7231 // TODO(zmo): crbug.com/481184
7232 // On Desktop GL with versions lower than 4.3, we need to emulate
7233 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7234 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7235 return DoDrawArrays("glDrawArrays",
7236 false,
7237 static_cast<GLenum>(c.mode),
7238 static_cast<GLint>(c.first),
7239 static_cast<GLsizei>(c.count),
7243 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7244 uint32 immediate_data_size,
7245 const void* cmd_data) {
7246 const gles2::cmds::DrawArraysInstancedANGLE& c =
7247 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7248 if (!features().angle_instanced_arrays) {
7249 LOCAL_SET_GL_ERROR(
7250 GL_INVALID_OPERATION,
7251 "glDrawArraysInstancedANGLE", "function not available");
7252 return error::kNoError;
7254 return DoDrawArrays("glDrawArraysIntancedANGLE",
7255 true,
7256 static_cast<GLenum>(c.mode),
7257 static_cast<GLint>(c.first),
7258 static_cast<GLsizei>(c.count),
7259 static_cast<GLsizei>(c.primcount));
7262 error::Error GLES2DecoderImpl::DoDrawElements(
7263 const char* function_name,
7264 bool instanced,
7265 GLenum mode,
7266 GLsizei count,
7267 GLenum type,
7268 int32 offset,
7269 GLsizei primcount) {
7270 error::Error error = WillAccessBoundFramebufferForDraw();
7271 if (error != error::kNoError)
7272 return error;
7273 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7274 LOCAL_SET_GL_ERROR(
7275 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7276 return error::kNoError;
7279 if (count < 0) {
7280 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7281 return error::kNoError;
7283 if (offset < 0) {
7284 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7285 return error::kNoError;
7287 if (!validators_->draw_mode.IsValid(mode)) {
7288 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7289 return error::kNoError;
7291 if (!validators_->index_type.IsValid(type)) {
7292 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7293 return error::kNoError;
7295 if (primcount < 0) {
7296 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7297 return error::kNoError;
7300 if (!CheckBoundFramebuffersValid(function_name)) {
7301 return error::kNoError;
7304 if (count == 0 || primcount == 0) {
7305 return error::kNoError;
7308 GLuint max_vertex_accessed;
7309 Buffer* element_array_buffer =
7310 state_.vertex_attrib_manager->element_array_buffer();
7312 if (!element_array_buffer->GetMaxValueForRange(
7313 offset, count, type, &max_vertex_accessed)) {
7314 LOCAL_SET_GL_ERROR(
7315 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7316 return error::kNoError;
7319 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7320 if (!ClearUnclearedTextures()) {
7321 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7322 return error::kNoError;
7324 bool simulated_attrib_0 = false;
7325 if (!SimulateAttrib0(
7326 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7327 return error::kNoError;
7329 bool simulated_fixed_attribs = false;
7330 if (SimulateFixedAttribs(
7331 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7332 primcount)) {
7333 bool textures_set = !PrepareTexturesForRender();
7334 ApplyDirtyState();
7335 // TODO(gman): Refactor to hide these details in BufferManager or
7336 // VertexAttribManager.
7337 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7338 bool used_client_side_array = false;
7339 if (element_array_buffer->IsClientSideArray()) {
7340 used_client_side_array = true;
7341 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7342 indices = element_array_buffer->GetRange(offset, 0);
7345 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7346 if (!instanced) {
7347 glDrawElements(mode, count, type, indices);
7348 } else {
7349 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7352 if (used_client_side_array) {
7353 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7354 element_array_buffer->service_id());
7357 if (textures_set) {
7358 RestoreStateForTextures();
7360 if (simulated_fixed_attribs) {
7361 RestoreStateForSimulatedFixedAttribs();
7364 if (simulated_attrib_0) {
7365 // We don't have to restore attrib 0 generic data at the end of this
7366 // function even if it is simulated. This is because we will simulate
7367 // it in each draw call, and attrib 0 generic data queries use cached
7368 // values instead of passing down to the underlying driver.
7369 RestoreStateForAttrib(0, false);
7372 return error::kNoError;
7375 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7376 const void* cmd_data) {
7377 // TODO(zmo): crbug.com/481184
7378 // On Desktop GL with versions lower than 4.3, we need to emulate
7379 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7380 const gles2::cmds::DrawElements& c =
7381 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7382 return DoDrawElements("glDrawElements",
7383 false,
7384 static_cast<GLenum>(c.mode),
7385 static_cast<GLsizei>(c.count),
7386 static_cast<GLenum>(c.type),
7387 static_cast<int32>(c.index_offset),
7391 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7392 uint32 immediate_data_size,
7393 const void* cmd_data) {
7394 const gles2::cmds::DrawElementsInstancedANGLE& c =
7395 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7396 if (!features().angle_instanced_arrays) {
7397 LOCAL_SET_GL_ERROR(
7398 GL_INVALID_OPERATION,
7399 "glDrawElementsInstancedANGLE", "function not available");
7400 return error::kNoError;
7402 return DoDrawElements("glDrawElementsInstancedANGLE",
7403 true,
7404 static_cast<GLenum>(c.mode),
7405 static_cast<GLsizei>(c.count),
7406 static_cast<GLenum>(c.type),
7407 static_cast<int32>(c.index_offset),
7408 static_cast<GLsizei>(c.primcount));
7411 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7412 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7413 GLuint max_vertex_accessed = 0;
7414 Buffer* buffer = GetBuffer(buffer_id);
7415 if (!buffer) {
7416 // TODO(gman): Should this be a GL error or a command buffer error?
7417 LOCAL_SET_GL_ERROR(
7418 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7419 } else {
7420 if (!buffer->GetMaxValueForRange(
7421 offset, count, type, &max_vertex_accessed)) {
7422 // TODO(gman): Should this be a GL error or a command buffer error?
7423 LOCAL_SET_GL_ERROR(
7424 GL_INVALID_OPERATION,
7425 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7428 return max_vertex_accessed;
7431 void GLES2DecoderImpl::DoShaderSource(
7432 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7433 std::string str;
7434 for (GLsizei ii = 0; ii < count; ++ii) {
7435 if (length && length[ii] > 0)
7436 str.append(data[ii], length[ii]);
7437 else
7438 str.append(data[ii]);
7440 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7441 if (!shader) {
7442 return;
7444 // Note: We don't actually call glShaderSource here. We wait until
7445 // we actually compile the shader.
7446 shader->set_source(str);
7449 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7450 GLuint client_program_id, GLsizei count, const char* const* varyings,
7451 GLenum buffer_mode) {
7452 Program* program = GetProgramInfoNotShader(
7453 client_program_id, "glTransformFeedbackVaryings");
7454 if (!program) {
7455 return;
7457 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7458 glTransformFeedbackVaryings(
7459 program->service_id(), count, varyings, buffer_mode);
7462 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7463 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7464 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7465 if (!shader) {
7466 return;
7469 scoped_refptr<ShaderTranslatorInterface> translator;
7470 if (use_shader_translator_) {
7471 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7472 vertex_translator_ : fragment_translator_;
7475 const Shader::TranslatedShaderSourceType source_type =
7476 feature_info_->feature_flags().angle_translated_shader_source ?
7477 Shader::kANGLE : Shader::kGL;
7478 shader->RequestCompile(translator, source_type);
7481 void GLES2DecoderImpl::DoGetShaderiv(
7482 GLuint shader_id, GLenum pname, GLint* params) {
7483 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7484 if (!shader) {
7485 return;
7488 // Compile now for statuses that require it.
7489 switch (pname) {
7490 case GL_COMPILE_STATUS:
7491 case GL_INFO_LOG_LENGTH:
7492 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7493 shader->DoCompile();
7494 break;
7496 default:
7497 break;
7500 switch (pname) {
7501 case GL_SHADER_SOURCE_LENGTH:
7502 *params = shader->source().size();
7503 if (*params)
7504 ++(*params);
7505 return;
7506 case GL_COMPILE_STATUS:
7507 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7508 return;
7509 case GL_INFO_LOG_LENGTH:
7510 *params = shader->log_info().size();
7511 if (*params)
7512 ++(*params);
7513 return;
7514 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7515 *params = shader->translated_source().size();
7516 if (*params)
7517 ++(*params);
7518 return;
7519 default:
7520 break;
7522 glGetShaderiv(shader->service_id(), pname, params);
7525 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7526 const void* cmd_data) {
7527 const gles2::cmds::GetShaderSource& c =
7528 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7529 GLuint shader_id = c.shader;
7530 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7531 Bucket* bucket = CreateBucket(bucket_id);
7532 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7533 if (!shader || shader->source().empty()) {
7534 bucket->SetSize(0);
7535 return error::kNoError;
7537 bucket->SetFromString(shader->source().c_str());
7538 return error::kNoError;
7541 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7542 uint32 immediate_data_size,
7543 const void* cmd_data) {
7544 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7545 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7546 cmd_data);
7547 GLuint shader_id = c.shader;
7548 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7549 Bucket* bucket = CreateBucket(bucket_id);
7550 Shader* shader = GetShaderInfoNotProgram(
7551 shader_id, "glGetTranslatedShaderSourceANGLE");
7552 if (!shader) {
7553 bucket->SetSize(0);
7554 return error::kNoError;
7557 // Make sure translator has been utilized in compile.
7558 shader->DoCompile();
7560 bucket->SetFromString(shader->translated_source().c_str());
7561 return error::kNoError;
7564 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7565 uint32 immediate_data_size,
7566 const void* cmd_data) {
7567 const gles2::cmds::GetProgramInfoLog& c =
7568 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7569 GLuint program_id = c.program;
7570 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7571 Bucket* bucket = CreateBucket(bucket_id);
7572 Program* program = GetProgramInfoNotShader(
7573 program_id, "glGetProgramInfoLog");
7574 if (!program || !program->log_info()) {
7575 bucket->SetFromString("");
7576 return error::kNoError;
7578 bucket->SetFromString(program->log_info()->c_str());
7579 return error::kNoError;
7582 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7583 uint32 immediate_data_size,
7584 const void* cmd_data) {
7585 const gles2::cmds::GetShaderInfoLog& c =
7586 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7587 GLuint shader_id = c.shader;
7588 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7589 Bucket* bucket = CreateBucket(bucket_id);
7590 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7591 if (!shader) {
7592 bucket->SetFromString("");
7593 return error::kNoError;
7596 // Shader must be compiled in order to get the info log.
7597 shader->DoCompile();
7599 bucket->SetFromString(shader->log_info().c_str());
7600 return error::kNoError;
7603 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7604 return state_.GetEnabled(cap);
7607 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7608 const Buffer* buffer = GetBuffer(client_id);
7609 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7612 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7613 const Framebuffer* framebuffer =
7614 GetFramebuffer(client_id);
7615 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7618 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7619 // IsProgram is true for programs as soon as they are created, until they are
7620 // deleted and no longer in use.
7621 const Program* program = GetProgram(client_id);
7622 return program != NULL && !program->IsDeleted();
7625 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7626 const Renderbuffer* renderbuffer =
7627 GetRenderbuffer(client_id);
7628 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7631 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7632 // IsShader is true for shaders as soon as they are created, until they
7633 // are deleted and not attached to any programs.
7634 const Shader* shader = GetShader(client_id);
7635 return shader != NULL && !shader->IsDeleted();
7638 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7639 const TextureRef* texture_ref = GetTexture(client_id);
7640 return texture_ref && texture_ref->texture()->IsValid();
7643 void GLES2DecoderImpl::DoAttachShader(
7644 GLuint program_client_id, GLint shader_client_id) {
7645 Program* program = GetProgramInfoNotShader(
7646 program_client_id, "glAttachShader");
7647 if (!program) {
7648 return;
7650 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7651 if (!shader) {
7652 return;
7654 if (!program->AttachShader(shader_manager(), shader)) {
7655 LOCAL_SET_GL_ERROR(
7656 GL_INVALID_OPERATION,
7657 "glAttachShader",
7658 "can not attach more than one shader of the same type.");
7659 return;
7661 glAttachShader(program->service_id(), shader->service_id());
7664 void GLES2DecoderImpl::DoDetachShader(
7665 GLuint program_client_id, GLint shader_client_id) {
7666 Program* program = GetProgramInfoNotShader(
7667 program_client_id, "glDetachShader");
7668 if (!program) {
7669 return;
7671 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7672 if (!shader) {
7673 return;
7675 if (!program->DetachShader(shader_manager(), shader)) {
7676 LOCAL_SET_GL_ERROR(
7677 GL_INVALID_OPERATION,
7678 "glDetachShader", "shader not attached to program");
7679 return;
7681 glDetachShader(program->service_id(), shader->service_id());
7684 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7685 Program* program = GetProgramInfoNotShader(
7686 program_client_id, "glValidateProgram");
7687 if (!program) {
7688 return;
7690 program->Validate();
7693 void GLES2DecoderImpl::GetVertexAttribHelper(
7694 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7695 switch (pname) {
7696 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7698 Buffer* buffer = attrib->buffer();
7699 if (buffer && !buffer->IsDeleted()) {
7700 GLuint client_id;
7701 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7702 *params = client_id;
7704 break;
7706 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7707 *params = attrib->enabled();
7708 break;
7709 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7710 *params = attrib->size();
7711 break;
7712 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7713 *params = attrib->gl_stride();
7714 break;
7715 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7716 *params = attrib->type();
7717 break;
7718 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7719 *params = attrib->normalized();
7720 break;
7721 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7722 *params = attrib->divisor();
7723 break;
7724 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7725 *params = attrib->integer();
7726 break;
7727 default:
7728 NOTREACHED();
7729 break;
7733 void GLES2DecoderImpl::DoGetTexParameterfv(
7734 GLenum target, GLenum pname, GLfloat* params) {
7735 InitTextureMaxAnisotropyIfNeeded(target, pname);
7736 glGetTexParameterfv(target, pname, params);
7739 void GLES2DecoderImpl::DoGetTexParameteriv(
7740 GLenum target, GLenum pname, GLint* params) {
7741 InitTextureMaxAnisotropyIfNeeded(target, pname);
7742 glGetTexParameteriv(target, pname, params);
7745 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7746 GLenum target, GLenum pname) {
7747 if (!workarounds().init_texture_max_anisotropy)
7748 return;
7749 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7750 !validators_->texture_parameter.IsValid(pname)) {
7751 return;
7754 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7755 &state_, target);
7756 if (!texture_ref) {
7757 LOCAL_SET_GL_ERROR(
7758 GL_INVALID_OPERATION,
7759 "glGetTexParamter{fi}v", "unknown texture for target");
7760 return;
7762 Texture* texture = texture_ref->texture();
7763 texture->InitTextureMaxAnisotropyIfNeeded(target);
7766 template <typename T>
7767 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7768 GLuint index, GLenum pname, T* params) {
7769 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7770 if (!attrib) {
7771 LOCAL_SET_GL_ERROR(
7772 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
7773 return;
7775 switch (pname) {
7776 case GL_CURRENT_VERTEX_ATTRIB:
7777 state_.attrib_values[index].GetValues(params);
7778 break;
7779 default: {
7780 GLint value = 0;
7781 GetVertexAttribHelper(attrib, pname, &value);
7782 *params = static_cast<T>(value);
7783 break;
7788 void GLES2DecoderImpl::DoGetVertexAttribfv(
7789 GLuint index, GLenum pname, GLfloat* params) {
7790 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
7793 void GLES2DecoderImpl::DoGetVertexAttribiv(
7794 GLuint index, GLenum pname, GLint* params) {
7795 DoGetVertexAttribImpl<GLint>(index, pname, params);
7798 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7799 GLuint index, GLenum pname, GLint* params) {
7800 DoGetVertexAttribImpl<GLint>(index, pname, params);
7803 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7804 GLuint index, GLenum pname, GLuint* params) {
7805 DoGetVertexAttribImpl<GLuint>(index, pname, params);
7808 template <typename T>
7809 bool GLES2DecoderImpl::SetVertexAttribValue(
7810 const char* function_name, GLuint index, const T* value) {
7811 if (index >= state_.attrib_values.size()) {
7812 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7813 return false;
7815 state_.attrib_values[index].SetValues(value);
7816 return true;
7819 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7820 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7821 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7822 glVertexAttrib1f(index, v0);
7826 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7827 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7828 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7829 glVertexAttrib2f(index, v0, v1);
7833 void GLES2DecoderImpl::DoVertexAttrib3f(
7834 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7835 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7836 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7837 glVertexAttrib3f(index, v0, v1, v2);
7841 void GLES2DecoderImpl::DoVertexAttrib4f(
7842 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7843 GLfloat v[4] = { v0, v1, v2, v3, };
7844 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7845 glVertexAttrib4f(index, v0, v1, v2, v3);
7849 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7850 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7851 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7852 glVertexAttrib1fv(index, v);
7856 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7857 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7858 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7859 glVertexAttrib2fv(index, v);
7863 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7864 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7865 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7866 glVertexAttrib3fv(index, v);
7870 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7871 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7872 glVertexAttrib4fv(index, v);
7876 void GLES2DecoderImpl::DoVertexAttribI4i(
7877 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
7878 GLint v[4] = { v0, v1, v2, v3 };
7879 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
7880 glVertexAttribI4i(index, v0, v1, v2, v3);
7884 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
7885 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
7886 glVertexAttribI4iv(index, v);
7890 void GLES2DecoderImpl::DoVertexAttribI4ui(
7891 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
7892 GLuint v[4] = { v0, v1, v2, v3 };
7893 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
7894 glVertexAttribI4ui(index, v0, v1, v2, v3);
7898 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
7899 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
7900 glVertexAttribI4uiv(index, v);
7904 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
7905 uint32 immediate_data_size,
7906 const void* cmd_data) {
7907 if (!unsafe_es3_apis_enabled())
7908 return error::kUnknownCommand;
7909 const gles2::cmds::VertexAttribIPointer& c =
7910 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
7912 if (!state_.bound_array_buffer.get() ||
7913 state_.bound_array_buffer->IsDeleted()) {
7914 if (state_.vertex_attrib_manager.get() ==
7915 state_.default_vertex_attrib_manager.get()) {
7916 LOCAL_SET_GL_ERROR(
7917 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
7918 return error::kNoError;
7919 } else if (c.offset != 0) {
7920 LOCAL_SET_GL_ERROR(
7921 GL_INVALID_VALUE,
7922 "glVertexAttribIPointer", "client side arrays are not allowed");
7923 return error::kNoError;
7927 GLuint indx = c.indx;
7928 GLint size = c.size;
7929 GLenum type = c.type;
7930 GLsizei stride = c.stride;
7931 GLsizei offset = c.offset;
7932 const void* ptr = reinterpret_cast<const void*>(offset);
7933 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
7934 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
7935 return error::kNoError;
7937 if (!validators_->vertex_attrib_size.IsValid(size)) {
7938 LOCAL_SET_GL_ERROR(
7939 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
7940 return error::kNoError;
7942 if (indx >= group_->max_vertex_attribs()) {
7943 LOCAL_SET_GL_ERROR(
7944 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
7945 return error::kNoError;
7947 if (stride < 0) {
7948 LOCAL_SET_GL_ERROR(
7949 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
7950 return error::kNoError;
7952 if (stride > 255) {
7953 LOCAL_SET_GL_ERROR(
7954 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
7955 return error::kNoError;
7957 if (offset < 0) {
7958 LOCAL_SET_GL_ERROR(
7959 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
7960 return error::kNoError;
7962 GLsizei component_size =
7963 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7964 // component_size must be a power of two to use & as optimized modulo.
7965 DCHECK(GLES2Util::IsPOT(component_size));
7966 if (offset & (component_size - 1)) {
7967 LOCAL_SET_GL_ERROR(
7968 GL_INVALID_OPERATION,
7969 "glVertexAttribIPointer", "offset not valid for type");
7970 return error::kNoError;
7972 if (stride & (component_size - 1)) {
7973 LOCAL_SET_GL_ERROR(
7974 GL_INVALID_OPERATION,
7975 "glVertexAttribIPointer", "stride not valid for type");
7976 return error::kNoError;
7978 state_.vertex_attrib_manager
7979 ->SetAttribInfo(indx,
7980 state_.bound_array_buffer.get(),
7981 size,
7982 type,
7983 GL_FALSE,
7984 stride,
7985 stride != 0 ? stride : component_size * size,
7986 offset,
7987 GL_TRUE);
7988 glVertexAttribIPointer(indx, size, type, stride, ptr);
7989 return error::kNoError;
7992 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7993 uint32 immediate_data_size,
7994 const void* cmd_data) {
7995 const gles2::cmds::VertexAttribPointer& c =
7996 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7998 if (!state_.bound_array_buffer.get() ||
7999 state_.bound_array_buffer->IsDeleted()) {
8000 if (state_.vertex_attrib_manager.get() ==
8001 state_.default_vertex_attrib_manager.get()) {
8002 LOCAL_SET_GL_ERROR(
8003 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8004 return error::kNoError;
8005 } else if (c.offset != 0) {
8006 LOCAL_SET_GL_ERROR(
8007 GL_INVALID_VALUE,
8008 "glVertexAttribPointer", "client side arrays are not allowed");
8009 return error::kNoError;
8013 GLuint indx = c.indx;
8014 GLint size = c.size;
8015 GLenum type = c.type;
8016 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8017 GLsizei stride = c.stride;
8018 GLsizei offset = c.offset;
8019 const void* ptr = reinterpret_cast<const void*>(offset);
8020 if (!validators_->vertex_attrib_type.IsValid(type)) {
8021 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8022 return error::kNoError;
8024 if (!validators_->vertex_attrib_size.IsValid(size)) {
8025 LOCAL_SET_GL_ERROR(
8026 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8027 return error::kNoError;
8029 if (indx >= group_->max_vertex_attribs()) {
8030 LOCAL_SET_GL_ERROR(
8031 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8032 return error::kNoError;
8034 if (stride < 0) {
8035 LOCAL_SET_GL_ERROR(
8036 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8037 return error::kNoError;
8039 if (stride > 255) {
8040 LOCAL_SET_GL_ERROR(
8041 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8042 return error::kNoError;
8044 if (offset < 0) {
8045 LOCAL_SET_GL_ERROR(
8046 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8047 return error::kNoError;
8049 GLsizei component_size =
8050 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8051 // component_size must be a power of two to use & as optimized modulo.
8052 DCHECK(GLES2Util::IsPOT(component_size));
8053 if (offset & (component_size - 1)) {
8054 LOCAL_SET_GL_ERROR(
8055 GL_INVALID_OPERATION,
8056 "glVertexAttribPointer", "offset not valid for type");
8057 return error::kNoError;
8059 if (stride & (component_size - 1)) {
8060 LOCAL_SET_GL_ERROR(
8061 GL_INVALID_OPERATION,
8062 "glVertexAttribPointer", "stride not valid for type");
8063 return error::kNoError;
8065 state_.vertex_attrib_manager
8066 ->SetAttribInfo(indx,
8067 state_.bound_array_buffer.get(),
8068 size,
8069 type,
8070 normalized,
8071 stride,
8072 stride != 0 ? stride : component_size * size,
8073 offset,
8074 GL_FALSE);
8075 // We support GL_FIXED natively on EGL/GLES2 implementations
8076 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8077 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8079 return error::kNoError;
8082 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8083 GLsizei height) {
8084 state_.viewport_x = x;
8085 state_.viewport_y = y;
8086 state_.viewport_width = std::min(width, viewport_max_width_);
8087 state_.viewport_height = std::min(height, viewport_max_height_);
8088 glViewport(x, y, width, height);
8091 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8092 uint32 immediate_data_size,
8093 const void* cmd_data) {
8094 const gles2::cmds::VertexAttribDivisorANGLE& c =
8095 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8096 if (!features().angle_instanced_arrays) {
8097 LOCAL_SET_GL_ERROR(
8098 GL_INVALID_OPERATION,
8099 "glVertexAttribDivisorANGLE", "function not available");
8100 return error::kNoError;
8102 GLuint index = c.index;
8103 GLuint divisor = c.divisor;
8104 if (index >= group_->max_vertex_attribs()) {
8105 LOCAL_SET_GL_ERROR(
8106 GL_INVALID_VALUE,
8107 "glVertexAttribDivisorANGLE", "index out of range");
8108 return error::kNoError;
8111 state_.vertex_attrib_manager->SetDivisor(
8112 index,
8113 divisor);
8114 glVertexAttribDivisorANGLE(index, divisor);
8115 return error::kNoError;
8118 template <typename pixel_data_type>
8119 static void WriteAlphaData(
8120 void* pixels, uint32 row_count, uint32 channel_count,
8121 uint32 alpha_channel_index, uint32 unpadded_row_size,
8122 uint32 padded_row_size, pixel_data_type alpha_value) {
8123 DCHECK_GT(channel_count, 0U);
8124 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8125 uint32 unpadded_row_size_in_elements =
8126 unpadded_row_size / sizeof(pixel_data_type);
8127 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8128 uint32 padded_row_size_in_elements =
8129 padded_row_size / sizeof(pixel_data_type);
8130 pixel_data_type* dst =
8131 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8132 for (uint32 yy = 0; yy < row_count; ++yy) {
8133 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8134 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8135 *d = alpha_value;
8137 dst += padded_row_size_in_elements;
8141 void GLES2DecoderImpl::FinishReadPixels(
8142 const cmds::ReadPixels& c,
8143 GLuint buffer) {
8144 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8145 GLsizei width = c.width;
8146 GLsizei height = c.height;
8147 GLenum format = c.format;
8148 GLenum type = c.type;
8149 typedef cmds::ReadPixels::Result Result;
8150 uint32 pixels_size;
8151 Result* result = NULL;
8152 if (c.result_shm_id != 0) {
8153 result = GetSharedMemoryAs<Result*>(
8154 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8155 if (!result) {
8156 if (buffer != 0) {
8157 glDeleteBuffersARB(1, &buffer);
8159 return;
8162 GLES2Util::ComputeImageDataSizes(
8163 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8164 NULL, NULL);
8165 void* pixels = GetSharedMemoryAs<void*>(
8166 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8167 if (!pixels) {
8168 if (buffer != 0) {
8169 glDeleteBuffersARB(1, &buffer);
8171 return;
8174 if (buffer != 0) {
8175 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8176 void* data;
8177 if (features().map_buffer_range) {
8178 data = glMapBufferRange(
8179 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8180 } else {
8181 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8183 if (!data) {
8184 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8185 "Unable to map memory for readback.");
8186 return;
8188 memcpy(pixels, data, pixels_size);
8189 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8190 // have to restore the state.
8191 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8192 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8193 glDeleteBuffersARB(1, &buffer);
8196 if (result != NULL) {
8197 *result = true;
8200 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8201 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8202 if ((channels_exist & 0x0008) == 0 &&
8203 workarounds().clear_alpha_in_readpixels) {
8204 // Set the alpha to 255 because some drivers are buggy in this regard.
8205 uint32 temp_size;
8207 uint32 unpadded_row_size;
8208 uint32 padded_row_size;
8209 if (!GLES2Util::ComputeImageDataSizes(
8210 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8211 &unpadded_row_size, &padded_row_size)) {
8212 return;
8215 uint32 channel_count = 0;
8216 uint32 alpha_channel = 0;
8217 switch (format) {
8218 case GL_RGBA:
8219 case GL_BGRA_EXT:
8220 channel_count = 4;
8221 alpha_channel = 3;
8222 break;
8223 case GL_ALPHA:
8224 channel_count = 1;
8225 alpha_channel = 0;
8226 break;
8229 if (channel_count > 0) {
8230 switch (type) {
8231 case GL_UNSIGNED_BYTE:
8232 WriteAlphaData<uint8>(
8233 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8234 padded_row_size, 0xFF);
8235 break;
8236 case GL_FLOAT:
8237 WriteAlphaData<float>(
8238 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8239 padded_row_size, 1.0f);
8240 break;
8241 case GL_HALF_FLOAT:
8242 WriteAlphaData<uint16>(
8243 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8244 padded_row_size, 0x3C00);
8245 break;
8251 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8252 const void* cmd_data) {
8253 const gles2::cmds::ReadPixels& c =
8254 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8255 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8256 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8257 if (fbo_error != error::kNoError)
8258 return fbo_error;
8259 GLint x = c.x;
8260 GLint y = c.y;
8261 GLsizei width = c.width;
8262 GLsizei height = c.height;
8263 GLenum format = c.format;
8264 GLenum type = c.type;
8265 GLboolean async = static_cast<GLboolean>(c.async);
8266 if (width < 0 || height < 0) {
8267 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8268 return error::kNoError;
8270 typedef cmds::ReadPixels::Result Result;
8271 uint32 pixels_size;
8272 if (!GLES2Util::ComputeImageDataSizes(
8273 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8274 NULL, NULL)) {
8275 return error::kOutOfBounds;
8277 void* pixels = GetSharedMemoryAs<void*>(
8278 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8279 if (!pixels) {
8280 return error::kOutOfBounds;
8282 Result* result = NULL;
8283 if (c.result_shm_id != 0) {
8284 result = GetSharedMemoryAs<Result*>(
8285 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8286 if (!result) {
8287 return error::kOutOfBounds;
8291 if (!validators_->read_pixel_format.IsValid(format)) {
8292 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8293 return error::kNoError;
8295 if (!validators_->read_pixel_type.IsValid(type)) {
8296 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8297 return error::kNoError;
8299 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
8300 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
8301 // format and type are acceptable enums but not guaranteed to be supported
8302 // for this framebuffer. Have to ask gl if they are valid.
8303 GLint preferred_format = 0;
8304 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8305 GLint preferred_type = 0;
8306 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8307 if (format != static_cast<GLenum>(preferred_format) ||
8308 type != static_cast<GLenum>(preferred_type)) {
8309 LOCAL_SET_GL_ERROR(
8310 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
8311 "with the current read framebuffer");
8312 return error::kNoError;
8315 if (width == 0 || height == 0) {
8316 return error::kNoError;
8319 // Get the size of the current fbo or backbuffer.
8320 gfx::Size max_size = GetBoundReadFrameBufferSize();
8322 int32 max_x;
8323 int32 max_y;
8324 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8325 LOCAL_SET_GL_ERROR(
8326 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8327 return error::kNoError;
8330 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8331 return error::kNoError;
8334 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8335 return error::kNoError;
8338 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8340 ScopedResolvedFrameBufferBinder binder(this, false, true);
8342 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8343 // The user requested an out of range area. Get the results 1 line
8344 // at a time.
8345 uint32 temp_size;
8346 uint32 unpadded_row_size;
8347 uint32 padded_row_size;
8348 if (!GLES2Util::ComputeImageDataSizes(
8349 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8350 &unpadded_row_size, &padded_row_size)) {
8351 LOCAL_SET_GL_ERROR(
8352 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8353 return error::kNoError;
8356 GLint dest_x_offset = std::max(-x, 0);
8357 uint32 dest_row_offset;
8358 if (!GLES2Util::ComputeImageDataSizes(
8359 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8360 &dest_row_offset, NULL, NULL)) {
8361 LOCAL_SET_GL_ERROR(
8362 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8363 return error::kNoError;
8366 // Copy each row into the larger dest rect.
8367 int8* dst = static_cast<int8*>(pixels);
8368 GLint read_x = std::max(0, x);
8369 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8370 GLint read_width = read_end_x - read_x;
8371 for (GLint yy = 0; yy < height; ++yy) {
8372 GLint ry = y + yy;
8374 // Clear the row.
8375 memset(dst, 0, unpadded_row_size);
8377 // If the row is in range, copy it.
8378 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8379 glReadPixels(
8380 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8382 dst += padded_row_size;
8384 } else {
8385 if (async && features().use_async_readpixels) {
8386 GLuint buffer = 0;
8387 glGenBuffersARB(1, &buffer);
8388 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8389 // For ANGLE client version 2, GL_STREAM_READ is not available.
8390 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8391 GL_STATIC_DRAW : GL_STREAM_READ;
8392 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8393 GLenum error = glGetError();
8394 if (error == GL_NO_ERROR) {
8395 glReadPixels(x, y, width, height, format, type, 0);
8396 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8397 new FenceCallback()));
8398 WaitForReadPixels(base::Bind(
8399 &GLES2DecoderImpl::FinishReadPixels,
8400 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8401 <GLES2DecoderImpl>(this),
8402 c, buffer));
8403 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8404 return error::kNoError;
8405 } else {
8406 // On error, unbind pack buffer and fall through to sync readpixels
8407 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8408 glDeleteBuffersARB(1, &buffer);
8411 glReadPixels(x, y, width, height, format, type, pixels);
8413 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8414 if (error == GL_NO_ERROR) {
8415 if (result != NULL) {
8416 *result = true;
8418 FinishReadPixels(c, 0);
8421 return error::kNoError;
8424 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8425 const void* cmd_data) {
8426 const gles2::cmds::PixelStorei& c =
8427 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8428 GLenum pname = c.pname;
8429 GLenum param = c.param;
8430 if (!validators_->pixel_store.IsValid(pname)) {
8431 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8432 return error::kNoError;
8434 switch (pname) {
8435 case GL_PACK_ALIGNMENT:
8436 case GL_UNPACK_ALIGNMENT:
8437 if (!validators_->pixel_store_alignment.IsValid(param)) {
8438 LOCAL_SET_GL_ERROR(
8439 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8440 return error::kNoError;
8442 break;
8443 case GL_UNPACK_FLIP_Y_CHROMIUM:
8444 unpack_flip_y_ = (param != 0);
8445 return error::kNoError;
8446 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
8447 unpack_premultiply_alpha_ = (param != 0);
8448 return error::kNoError;
8449 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
8450 unpack_unpremultiply_alpha_ = (param != 0);
8451 return error::kNoError;
8452 default:
8453 break;
8455 glPixelStorei(pname, param);
8456 switch (pname) {
8457 case GL_PACK_ALIGNMENT:
8458 state_.pack_alignment = param;
8459 break;
8460 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8461 state_.pack_reverse_row_order = (param != 0);
8462 break;
8463 case GL_UNPACK_ALIGNMENT:
8464 state_.unpack_alignment = param;
8465 break;
8466 default:
8467 // Validation should have prevented us from getting here.
8468 NOTREACHED();
8469 break;
8471 return error::kNoError;
8474 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8475 uint32 immediate_data_size,
8476 const void* cmd_data) {
8477 const gles2::cmds::PostSubBufferCHROMIUM& c =
8478 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8479 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8481 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8483 if (!supports_post_sub_buffer_) {
8484 LOCAL_SET_GL_ERROR(
8485 GL_INVALID_OPERATION,
8486 "glPostSubBufferCHROMIUM", "command not supported by surface");
8487 return error::kNoError;
8489 bool is_tracing;
8490 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8491 &is_tracing);
8492 if (is_tracing) {
8493 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8494 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8495 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8496 is_offscreen ? offscreen_size_ : surface_->GetSize());
8498 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
8499 gfx::SwapResult::SWAP_FAILED) {
8500 return error::kNoError;
8501 } else {
8502 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8503 return error::kLostContext;
8507 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8508 uint32 immediate_data_size,
8509 const void* cmd_data) {
8510 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8511 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8512 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8513 if (!ref) {
8514 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8515 "glScheduleOverlayPlaneCHROMIUM",
8516 "unknown texture");
8517 return error::kNoError;
8519 gfx::GLImage* image =
8520 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8521 if (!image) {
8522 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8523 "glScheduleOverlayPlaneCHROMIUM",
8524 "unsupported texture format");
8525 return error::kNoError;
8527 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8528 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8529 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8530 "glScheduleOverlayPlaneCHROMIUM",
8531 "invalid transform enum");
8532 return error::kNoError;
8534 if (!surface_->ScheduleOverlayPlane(
8535 c.plane_z_order,
8536 transform,
8537 image,
8538 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8539 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8540 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8541 "glScheduleOverlayPlaneCHROMIUM",
8542 "failed to schedule overlay");
8544 return error::kNoError;
8547 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8548 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8549 const std::string& name_str) {
8550 if (!StringIsValidForGLES(name_str.c_str())) {
8551 LOCAL_SET_GL_ERROR(
8552 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8553 return error::kNoError;
8555 Program* program = GetProgramInfoNotShader(
8556 client_id, "glGetAttribLocation");
8557 if (!program) {
8558 return error::kNoError;
8560 if (!program->IsValid()) {
8561 LOCAL_SET_GL_ERROR(
8562 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8563 return error::kNoError;
8565 GLint* location = GetSharedMemoryAs<GLint*>(
8566 location_shm_id, location_shm_offset, sizeof(GLint));
8567 if (!location) {
8568 return error::kOutOfBounds;
8570 // Require the client to init this incase the context is lost and we are no
8571 // longer executing commands.
8572 if (*location != -1) {
8573 return error::kGenericError;
8575 *location = program->GetAttribLocation(name_str);
8576 return error::kNoError;
8579 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8580 uint32 immediate_data_size,
8581 const void* cmd_data) {
8582 const gles2::cmds::GetAttribLocation& c =
8583 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8584 Bucket* bucket = GetBucket(c.name_bucket_id);
8585 if (!bucket) {
8586 return error::kInvalidArguments;
8588 std::string name_str;
8589 if (!bucket->GetAsString(&name_str)) {
8590 return error::kInvalidArguments;
8592 return GetAttribLocationHelper(
8593 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8596 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8597 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8598 const std::string& name_str) {
8599 if (!StringIsValidForGLES(name_str.c_str())) {
8600 LOCAL_SET_GL_ERROR(
8601 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8602 return error::kNoError;
8604 Program* program = GetProgramInfoNotShader(
8605 client_id, "glGetUniformLocation");
8606 if (!program) {
8607 return error::kNoError;
8609 if (!program->IsValid()) {
8610 LOCAL_SET_GL_ERROR(
8611 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8612 return error::kNoError;
8614 GLint* location = GetSharedMemoryAs<GLint*>(
8615 location_shm_id, location_shm_offset, sizeof(GLint));
8616 if (!location) {
8617 return error::kOutOfBounds;
8619 // Require the client to init this incase the context is lost an we are no
8620 // longer executing commands.
8621 if (*location != -1) {
8622 return error::kGenericError;
8624 *location = program->GetUniformFakeLocation(name_str);
8625 return error::kNoError;
8628 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8629 uint32 immediate_data_size,
8630 const void* cmd_data) {
8631 const gles2::cmds::GetUniformLocation& c =
8632 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8633 Bucket* bucket = GetBucket(c.name_bucket_id);
8634 if (!bucket) {
8635 return error::kInvalidArguments;
8637 std::string name_str;
8638 if (!bucket->GetAsString(&name_str)) {
8639 return error::kInvalidArguments;
8641 return GetUniformLocationHelper(
8642 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8645 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8646 uint32 immediate_data_size,
8647 const void* cmd_data) {
8648 if (!unsafe_es3_apis_enabled())
8649 return error::kUnknownCommand;
8650 const gles2::cmds::GetUniformIndices& c =
8651 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8652 Bucket* bucket = GetBucket(c.names_bucket_id);
8653 if (!bucket) {
8654 return error::kInvalidArguments;
8656 GLsizei count = 0;
8657 std::vector<char*> names;
8658 std::vector<GLint> len;
8659 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8660 return error::kInvalidArguments;
8662 typedef cmds::GetUniformIndices::Result Result;
8663 Result* result = GetSharedMemoryAs<Result*>(
8664 c.indices_shm_id, c.indices_shm_offset,
8665 Result::ComputeSize(static_cast<size_t>(count)));
8666 GLuint* indices = result ? result->GetData() : NULL;
8667 if (indices == NULL) {
8668 return error::kOutOfBounds;
8670 // Check that the client initialized the result.
8671 if (result->size != 0) {
8672 return error::kInvalidArguments;
8674 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8675 if (!program) {
8676 return error::kNoError;
8678 GLuint service_id = program->service_id();
8679 GLint link_status = GL_FALSE;
8680 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8681 if (link_status != GL_TRUE) {
8682 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8683 "glGetUniformIndices", "program not linked");
8684 return error::kNoError;
8686 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8687 glGetUniformIndices(service_id, count, &names[0], indices);
8688 GLenum error = glGetError();
8689 if (error == GL_NO_ERROR) {
8690 result->SetNumResults(count);
8691 } else {
8692 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8694 return error::kNoError;
8697 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8698 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8699 const std::string& name_str) {
8700 GLint* location = GetSharedMemoryAs<GLint*>(
8701 location_shm_id, location_shm_offset, sizeof(GLint));
8702 if (!location) {
8703 return error::kOutOfBounds;
8705 // Require the client to init this incase the context is lost and we are no
8706 // longer executing commands.
8707 if (*location != -1) {
8708 return error::kGenericError;
8710 Program* program = GetProgramInfoNotShader(
8711 client_id, "glGetFragDataLocation");
8712 if (!program) {
8713 return error::kNoError;
8715 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8716 return error::kNoError;
8719 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8720 uint32 immediate_data_size,
8721 const void* cmd_data) {
8722 if (!unsafe_es3_apis_enabled())
8723 return error::kUnknownCommand;
8724 const gles2::cmds::GetFragDataLocation& c =
8725 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8726 Bucket* bucket = GetBucket(c.name_bucket_id);
8727 if (!bucket) {
8728 return error::kInvalidArguments;
8730 std::string name_str;
8731 if (!bucket->GetAsString(&name_str)) {
8732 return error::kInvalidArguments;
8734 return GetFragDataLocationHelper(
8735 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8738 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8739 uint32 immediate_data_size, const void* cmd_data) {
8740 if (!unsafe_es3_apis_enabled())
8741 return error::kUnknownCommand;
8742 const gles2::cmds::GetUniformBlockIndex& c =
8743 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8744 Bucket* bucket = GetBucket(c.name_bucket_id);
8745 if (!bucket) {
8746 return error::kInvalidArguments;
8748 std::string name_str;
8749 if (!bucket->GetAsString(&name_str)) {
8750 return error::kInvalidArguments;
8752 GLuint* index = GetSharedMemoryAs<GLuint*>(
8753 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8754 if (!index) {
8755 return error::kOutOfBounds;
8757 // Require the client to init this in case the context is lost and we are no
8758 // longer executing commands.
8759 if (*index != GL_INVALID_INDEX) {
8760 return error::kGenericError;
8762 Program* program = GetProgramInfoNotShader(
8763 c.program, "glGetUniformBlockIndex");
8764 if (!program) {
8765 return error::kNoError;
8767 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8768 return error::kNoError;
8771 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8772 const void* cmd_data) {
8773 const gles2::cmds::GetString& c =
8774 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8775 GLenum name = static_cast<GLenum>(c.name);
8776 if (!validators_->string_type.IsValid(name)) {
8777 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8778 return error::kNoError;
8781 const char* str = nullptr;
8782 std::string extensions;
8783 switch (name) {
8784 case GL_VERSION:
8785 str = "OpenGL ES 2.0 Chromium";
8786 break;
8787 case GL_SHADING_LANGUAGE_VERSION:
8788 str = "OpenGL ES GLSL ES 1.0 Chromium";
8789 break;
8790 case GL_RENDERER:
8791 case GL_VENDOR:
8792 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8793 // They are used by WEBGL_debug_renderer_info.
8794 if (!force_webgl_glsl_validation_)
8795 str = "Chromium";
8796 else
8797 str = reinterpret_cast<const char*>(glGetString(name));
8798 break;
8799 case GL_EXTENSIONS:
8801 // For WebGL contexts, strip out the OES derivatives and
8802 // EXT frag depth extensions if they have not been enabled.
8803 if (force_webgl_glsl_validation_) {
8804 extensions = feature_info_->extensions();
8805 if (!derivatives_explicitly_enabled_) {
8806 size_t offset = extensions.find(kOESDerivativeExtension);
8807 if (std::string::npos != offset) {
8808 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8809 std::string());
8812 if (!frag_depth_explicitly_enabled_) {
8813 size_t offset = extensions.find(kEXTFragDepthExtension);
8814 if (std::string::npos != offset) {
8815 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8816 std::string());
8819 if (!draw_buffers_explicitly_enabled_) {
8820 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8821 if (std::string::npos != offset) {
8822 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8823 std::string());
8826 if (!shader_texture_lod_explicitly_enabled_) {
8827 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8828 if (std::string::npos != offset) {
8829 extensions.replace(offset,
8830 arraysize(kEXTShaderTextureLodExtension),
8831 std::string());
8834 } else {
8835 extensions = feature_info_->extensions().c_str();
8837 if (supports_post_sub_buffer_)
8838 extensions += " GL_CHROMIUM_post_sub_buffer";
8839 str = extensions.c_str();
8841 break;
8842 default:
8843 str = reinterpret_cast<const char*>(glGetString(name));
8844 break;
8846 Bucket* bucket = CreateBucket(c.bucket_id);
8847 bucket->SetFromString(str);
8848 return error::kNoError;
8851 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8852 const void* cmd_data) {
8853 const gles2::cmds::BufferData& c =
8854 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8855 GLenum target = static_cast<GLenum>(c.target);
8856 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8857 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8858 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8859 GLenum usage = static_cast<GLenum>(c.usage);
8860 const void* data = NULL;
8861 if (data_shm_id != 0 || data_shm_offset != 0) {
8862 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8863 if (!data) {
8864 return error::kOutOfBounds;
8867 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8868 return error::kNoError;
8871 void GLES2DecoderImpl::DoBufferSubData(
8872 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8873 // Just delegate it. Some validation is actually done before this.
8874 buffer_manager()->ValidateAndDoBufferSubData(
8875 &state_, target, offset, size, data);
8878 bool GLES2DecoderImpl::ClearLevel(
8879 Texture* texture,
8880 unsigned target,
8881 int level,
8882 unsigned internal_format,
8883 unsigned format,
8884 unsigned type,
8885 int width,
8886 int height,
8887 bool is_texture_immutable) {
8888 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8889 if (feature_info_->feature_flags().angle_depth_texture &&
8890 (channels & GLES2Util::kDepth) != 0) {
8891 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8892 // on depth formats.
8893 GLuint fb = 0;
8894 glGenFramebuffersEXT(1, &fb);
8895 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8897 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8898 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8899 GL_DEPTH_ATTACHMENT;
8901 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
8902 texture->service_id(), level);
8903 // ANGLE promises a depth only attachment ok.
8904 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8905 GL_FRAMEBUFFER_COMPLETE) {
8906 return false;
8908 glClearStencil(0);
8909 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8910 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8911 glClearDepth(1.0f);
8912 state_.SetDeviceDepthMask(GL_TRUE);
8913 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8914 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8916 RestoreClearState();
8918 glDeleteFramebuffersEXT(1, &fb);
8919 Framebuffer* framebuffer =
8920 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8921 GLuint fb_service_id =
8922 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8923 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8924 return true;
8927 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8929 uint32 size;
8930 uint32 padded_row_size;
8931 if (!GLES2Util::ComputeImageDataSizes(
8932 width, height, 1, format, type, state_.unpack_alignment, &size,
8933 NULL, &padded_row_size)) {
8934 return false;
8937 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8939 int tile_height;
8941 if (size > kMaxZeroSize) {
8942 if (kMaxZeroSize < padded_row_size) {
8943 // That'd be an awfully large texture.
8944 return false;
8946 // We should never have a large total size with a zero row size.
8947 DCHECK_GT(padded_row_size, 0U);
8948 tile_height = kMaxZeroSize / padded_row_size;
8949 if (!GLES2Util::ComputeImageDataSizes(
8950 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
8951 NULL, NULL)) {
8952 return false;
8954 } else {
8955 tile_height = height;
8958 // Assumes the size has already been checked.
8959 scoped_ptr<char[]> zero(new char[size]);
8960 memset(zero.get(), 0, size);
8961 glBindTexture(texture->target(), texture->service_id());
8963 bool has_images = texture->HasImages();
8964 GLint y = 0;
8965 while (y < height) {
8966 GLint h = y + tile_height > height ? height - y : tile_height;
8967 if (is_texture_immutable || h != height || has_images) {
8968 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8969 } else {
8970 glTexImage2D(
8971 target, level, internal_format, width, h, 0, format, type,
8972 zero.get());
8974 y += tile_height;
8976 TextureRef* bound_texture =
8977 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
8978 glBindTexture(texture->target(),
8979 bound_texture ? bound_texture->service_id() : 0);
8980 return true;
8983 namespace {
8985 const int kS3TCBlockWidth = 4;
8986 const int kS3TCBlockHeight = 4;
8987 const int kS3TCDXT1BlockSize = 8;
8988 const int kS3TCDXT3AndDXT5BlockSize = 16;
8989 const int kEACAndETC2BlockSize = 4;
8991 bool IsValidDXTSize(GLint level, GLsizei size) {
8992 return (size == 1) ||
8993 (size == 2) || !(size % kS3TCBlockWidth);
8996 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8997 return GLES2Util::IsPOT(size);
9000 } // anonymous namespace.
9002 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9003 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9004 GLenum format, GLsizei size) {
9005 base::CheckedNumeric<GLsizei> bytes_required(0);
9007 switch (format) {
9008 case GL_ATC_RGB_AMD:
9009 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9010 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9011 case GL_ETC1_RGB8_OES:
9012 bytes_required =
9013 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9014 bytes_required *=
9015 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9016 bytes_required *= kS3TCDXT1BlockSize;
9017 break;
9018 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9019 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9020 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9021 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9022 bytes_required =
9023 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9024 bytes_required *=
9025 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9026 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9027 break;
9028 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9029 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9030 bytes_required = std::max(width, 8);
9031 bytes_required *= std::max(height, 8);
9032 bytes_required *= 4;
9033 bytes_required += 7;
9034 bytes_required /= 8;
9035 break;
9036 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9037 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9038 bytes_required = std::max(width, 16);
9039 bytes_required *= std::max(height, 8);
9040 bytes_required *= 2;
9041 bytes_required += 7;
9042 bytes_required /= 8;
9043 break;
9045 // ES3 formats.
9046 case GL_COMPRESSED_R11_EAC:
9047 case GL_COMPRESSED_SIGNED_R11_EAC:
9048 case GL_COMPRESSED_RGB8_ETC2:
9049 case GL_COMPRESSED_SRGB8_ETC2:
9050 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9051 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9052 bytes_required =
9053 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9054 bytes_required *=
9055 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9056 bytes_required *= 8;
9057 bytes_required *= depth;
9058 break;
9059 case GL_COMPRESSED_RG11_EAC:
9060 case GL_COMPRESSED_SIGNED_RG11_EAC:
9061 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9062 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9063 bytes_required =
9064 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9065 bytes_required *=
9066 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9067 bytes_required *= 16;
9068 bytes_required *= depth;
9069 break;
9070 default:
9071 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9072 return false;
9075 if (!bytes_required.IsValid() || size != bytes_required.ValueOrDefault(0)) {
9076 LOCAL_SET_GL_ERROR(
9077 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9078 return false;
9081 return true;
9084 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9085 const char* function_name, GLenum target, GLint level,
9086 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9087 switch (format) {
9088 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9089 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9090 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9091 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9092 DCHECK_EQ(1, depth); // 2D formats.
9093 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9094 LOCAL_SET_GL_ERROR(
9095 GL_INVALID_OPERATION, function_name,
9096 "width or height invalid for level");
9097 return false;
9099 return true;
9100 case GL_ATC_RGB_AMD:
9101 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9102 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9103 case GL_ETC1_RGB8_OES:
9104 DCHECK_EQ(1, depth); // 2D formats.
9105 if (width <= 0 || height <= 0) {
9106 LOCAL_SET_GL_ERROR(
9107 GL_INVALID_OPERATION, function_name,
9108 "width or height invalid for level");
9109 return false;
9111 return true;
9112 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9113 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9114 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9115 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9116 DCHECK_EQ(1, depth); // 2D formats.
9117 if (!IsValidPVRTCSize(level, width) ||
9118 !IsValidPVRTCSize(level, height)) {
9119 LOCAL_SET_GL_ERROR(
9120 GL_INVALID_OPERATION, function_name,
9121 "width or height invalid for level");
9122 return false;
9124 return true;
9126 // ES3 formats.
9127 case GL_COMPRESSED_R11_EAC:
9128 case GL_COMPRESSED_SIGNED_R11_EAC:
9129 case GL_COMPRESSED_RG11_EAC:
9130 case GL_COMPRESSED_SIGNED_RG11_EAC:
9131 case GL_COMPRESSED_RGB8_ETC2:
9132 case GL_COMPRESSED_SRGB8_ETC2:
9133 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9134 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9135 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9136 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9137 if (width <= 0 || height <= 0 || depth <= 0) {
9138 LOCAL_SET_GL_ERROR(
9139 GL_INVALID_OPERATION, function_name,
9140 "width, height, or depth invalid");
9141 return false;
9143 if (target == GL_TEXTURE_3D) {
9144 LOCAL_SET_GL_ERROR(
9145 GL_INVALID_OPERATION, function_name,
9146 "target invalid for format");
9147 return false;
9149 return true;
9150 default:
9151 return false;
9155 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9156 const char* function_name,
9157 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9158 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9159 Texture* texture) {
9160 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9161 LOCAL_SET_GL_ERROR(
9162 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9163 return false;
9166 switch (format) {
9167 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9168 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9169 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9170 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9171 const int kBlockWidth = 4;
9172 const int kBlockHeight = 4;
9173 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9174 LOCAL_SET_GL_ERROR(
9175 GL_INVALID_OPERATION, function_name,
9176 "xoffset or yoffset not multiple of 4");
9177 return false;
9179 GLsizei tex_width = 0;
9180 GLsizei tex_height = 0;
9181 if (!texture->GetLevelSize(target, level,
9182 &tex_width, &tex_height, nullptr) ||
9183 width - xoffset > tex_width ||
9184 height - yoffset > tex_height) {
9185 LOCAL_SET_GL_ERROR(
9186 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9187 return false;
9189 return ValidateCompressedTexDimensions(
9190 function_name, target, level, width, height, 1, format);
9192 case GL_ATC_RGB_AMD:
9193 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9194 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9195 LOCAL_SET_GL_ERROR(
9196 GL_INVALID_OPERATION, function_name,
9197 "not supported for ATC textures");
9198 return false;
9200 case GL_ETC1_RGB8_OES: {
9201 LOCAL_SET_GL_ERROR(
9202 GL_INVALID_OPERATION, function_name,
9203 "not supported for ECT1_RGB8_OES textures");
9204 return false;
9206 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9207 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9208 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9209 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9210 if ((xoffset != 0) || (yoffset != 0)) {
9211 LOCAL_SET_GL_ERROR(
9212 GL_INVALID_OPERATION, function_name,
9213 "xoffset and yoffset must be zero");
9214 return false;
9216 GLsizei tex_width = 0;
9217 GLsizei tex_height = 0;
9218 if (!texture->GetLevelSize(target, level,
9219 &tex_width, &tex_height, nullptr) ||
9220 width != tex_width ||
9221 height != tex_height) {
9222 LOCAL_SET_GL_ERROR(
9223 GL_INVALID_OPERATION, function_name,
9224 "dimensions must match existing texture level dimensions");
9225 return false;
9227 return ValidateCompressedTexDimensions(
9228 function_name, target, level, width, height, 1, format);
9231 // ES3 formats
9232 case GL_COMPRESSED_R11_EAC:
9233 case GL_COMPRESSED_SIGNED_R11_EAC:
9234 case GL_COMPRESSED_RG11_EAC:
9235 case GL_COMPRESSED_SIGNED_RG11_EAC:
9236 case GL_COMPRESSED_RGB8_ETC2:
9237 case GL_COMPRESSED_SRGB8_ETC2:
9238 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9239 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9240 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9241 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9243 const int kBlockSize = 4;
9244 GLsizei tex_width, tex_height;
9245 if (target == GL_TEXTURE_3D ||
9246 !texture->GetLevelSize(target, level,
9247 &tex_width, &tex_height, nullptr) ||
9248 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9249 ((width % kBlockSize) && xoffset + width != tex_width) ||
9250 ((height % kBlockSize) && yoffset + height != tex_height)) {
9251 LOCAL_SET_GL_ERROR(
9252 GL_INVALID_OPERATION, function_name,
9253 "dimensions must match existing texture level dimensions");
9254 return false;
9256 return true;
9258 default:
9259 return false;
9263 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9264 GLenum target,
9265 GLint level,
9266 GLenum internal_format,
9267 GLsizei width,
9268 GLsizei height,
9269 GLint border,
9270 GLsizei image_size,
9271 const void* data) {
9272 if (!validators_->texture_target.IsValid(target)) {
9273 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9274 "glCompressedTexImage2D", target, "target");
9275 return error::kNoError;
9277 if (!validators_->compressed_texture_format.IsValid(
9278 internal_format)) {
9279 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9280 "glCompressedTexImage2D", internal_format, "internal_format");
9281 return error::kNoError;
9283 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9284 border != 0) {
9285 LOCAL_SET_GL_ERROR(
9286 GL_INVALID_VALUE,
9287 "glCompressedTexImage2D", "dimensions out of range");
9288 return error::kNoError;
9290 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9291 &state_, target);
9292 if (!texture_ref) {
9293 LOCAL_SET_GL_ERROR(
9294 GL_INVALID_VALUE,
9295 "glCompressedTexImage2D", "unknown texture target");
9296 return error::kNoError;
9298 Texture* texture = texture_ref->texture();
9299 if (texture->IsImmutable()) {
9300 LOCAL_SET_GL_ERROR(
9301 GL_INVALID_OPERATION,
9302 "glCompressedTexImage2D", "texture is immutable");
9303 return error::kNoError;
9306 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9307 width, height, 1, internal_format) ||
9308 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9309 1, internal_format, image_size)) {
9310 return error::kNoError;
9313 if (!EnsureGPUMemoryAvailable(image_size)) {
9314 LOCAL_SET_GL_ERROR(
9315 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9316 return error::kNoError;
9319 if (texture->IsAttachedToFramebuffer()) {
9320 framebuffer_state_.clear_state_dirty = true;
9323 scoped_ptr<int8[]> zero;
9324 if (!data) {
9325 zero.reset(new int8[image_size]);
9326 memset(zero.get(), 0, image_size);
9327 data = zero.get();
9329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9330 glCompressedTexImage2D(
9331 target, level, internal_format, width, height, border, image_size, data);
9332 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9333 if (error == GL_NO_ERROR) {
9334 texture_manager()->SetLevelInfo(
9335 texture_ref, target, level, internal_format,
9336 width, height, 1, border, 0, 0, true);
9339 // This may be a slow command. Exit command processing to allow for
9340 // context preemption and GPU watchdog checks.
9341 ExitCommandProcessingEarly();
9342 return error::kNoError;
9345 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9346 uint32 immediate_data_size,
9347 const void* cmd_data) {
9348 const gles2::cmds::CompressedTexImage2D& c =
9349 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9350 GLenum target = static_cast<GLenum>(c.target);
9351 GLint level = static_cast<GLint>(c.level);
9352 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9353 GLsizei width = static_cast<GLsizei>(c.width);
9354 GLsizei height = static_cast<GLsizei>(c.height);
9355 GLint border = static_cast<GLint>(c.border);
9356 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9357 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9358 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9359 const void* data = NULL;
9360 if (data_shm_id != 0 || data_shm_offset != 0) {
9361 data = GetSharedMemoryAs<const void*>(
9362 data_shm_id, data_shm_offset, image_size);
9363 if (!data) {
9364 return error::kOutOfBounds;
9367 return DoCompressedTexImage2D(
9368 target, level, internal_format, width, height, border, image_size, data);
9371 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9372 uint32 immediate_data_size,
9373 const void* cmd_data) {
9374 const gles2::cmds::CompressedTexImage2DBucket& c =
9375 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9376 GLenum target = static_cast<GLenum>(c.target);
9377 GLint level = static_cast<GLint>(c.level);
9378 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9379 GLsizei width = static_cast<GLsizei>(c.width);
9380 GLsizei height = static_cast<GLsizei>(c.height);
9381 GLint border = static_cast<GLint>(c.border);
9382 Bucket* bucket = GetBucket(c.bucket_id);
9383 if (!bucket) {
9384 return error::kInvalidArguments;
9386 uint32 data_size = bucket->size();
9387 GLsizei imageSize = data_size;
9388 const void* data = bucket->GetData(0, data_size);
9389 if (!data) {
9390 return error::kInvalidArguments;
9392 return DoCompressedTexImage2D(
9393 target, level, internal_format, width, height, border,
9394 imageSize, data);
9397 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9398 uint32 immediate_data_size,
9399 const void* cmd_data) {
9400 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9401 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9402 GLenum target = static_cast<GLenum>(c.target);
9403 GLint level = static_cast<GLint>(c.level);
9404 GLint xoffset = static_cast<GLint>(c.xoffset);
9405 GLint yoffset = static_cast<GLint>(c.yoffset);
9406 GLsizei width = static_cast<GLsizei>(c.width);
9407 GLsizei height = static_cast<GLsizei>(c.height);
9408 GLenum format = static_cast<GLenum>(c.format);
9409 Bucket* bucket = GetBucket(c.bucket_id);
9410 if (!bucket) {
9411 return error::kInvalidArguments;
9413 uint32 data_size = bucket->size();
9414 GLsizei imageSize = data_size;
9415 const void* data = bucket->GetData(0, data_size);
9416 if (!data) {
9417 return error::kInvalidArguments;
9419 if (!validators_->texture_target.IsValid(target)) {
9420 LOCAL_SET_GL_ERROR(
9421 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9422 return error::kNoError;
9424 if (!validators_->compressed_texture_format.IsValid(format)) {
9425 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9426 "glCompressedTexSubImage2D", format, "format");
9427 return error::kNoError;
9429 if (width < 0) {
9430 LOCAL_SET_GL_ERROR(
9431 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9432 return error::kNoError;
9434 if (height < 0) {
9435 LOCAL_SET_GL_ERROR(
9436 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9437 return error::kNoError;
9439 if (imageSize < 0) {
9440 LOCAL_SET_GL_ERROR(
9441 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9442 return error::kNoError;
9444 DoCompressedTexSubImage2D(
9445 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9446 return error::kNoError;
9449 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9450 GLenum target,
9451 GLint level,
9452 GLenum internal_format,
9453 GLsizei width,
9454 GLsizei height,
9455 GLsizei depth,
9456 GLint border,
9457 GLsizei image_size,
9458 const void* data) {
9459 if (!validators_->texture_3_d_target.IsValid(target)) {
9460 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9461 "glCompressedTexImage3D", target, "target");
9462 return error::kNoError;
9464 if (!validators_->compressed_texture_format.IsValid(
9465 internal_format)) {
9466 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9467 "glCompressedTexImage3D", internal_format, "internal_format");
9468 return error::kNoError;
9470 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9471 border != 0) {
9472 LOCAL_SET_GL_ERROR(
9473 GL_INVALID_VALUE,
9474 "glCompressedTexImage3D", "dimensions out of range");
9475 return error::kNoError;
9477 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9478 &state_, target);
9479 if (!texture_ref) {
9480 LOCAL_SET_GL_ERROR(
9481 GL_INVALID_VALUE,
9482 "glCompressedTexImage3D", "unknown texture target");
9483 return error::kNoError;
9485 Texture* texture = texture_ref->texture();
9486 if (texture->IsImmutable()) {
9487 LOCAL_SET_GL_ERROR(
9488 GL_INVALID_OPERATION,
9489 "glCompressedTexImage3D", "texture is immutable");
9490 return error::kNoError;
9493 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9494 width, height, depth, internal_format) ||
9495 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9496 depth, internal_format, image_size)) {
9497 return error::kNoError;
9500 if (!EnsureGPUMemoryAvailable(image_size)) {
9501 LOCAL_SET_GL_ERROR(
9502 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9503 return error::kNoError;
9506 if (texture->IsAttachedToFramebuffer()) {
9507 framebuffer_state_.clear_state_dirty = true;
9510 scoped_ptr<int8[]> zero;
9511 if (!data) {
9512 zero.reset(new int8[image_size]);
9513 memset(zero.get(), 0, image_size);
9514 data = zero.get();
9516 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9517 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9518 border, image_size, data);
9519 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9520 if (error == GL_NO_ERROR) {
9521 texture_manager()->SetLevelInfo(
9522 texture_ref, target, level, internal_format,
9523 width, height, depth, border, 0, 0, true);
9526 // This may be a slow command. Exit command processing to allow for
9527 // context preemption and GPU watchdog checks.
9528 ExitCommandProcessingEarly();
9529 return error::kNoError;
9532 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9533 uint32 immediate_data_size, const void* cmd_data) {
9534 if (!unsafe_es3_apis_enabled())
9535 return error::kUnknownCommand;
9537 const gles2::cmds::CompressedTexImage3D& c =
9538 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9539 GLenum target = static_cast<GLenum>(c.target);
9540 GLint level = static_cast<GLint>(c.level);
9541 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9542 GLsizei width = static_cast<GLsizei>(c.width);
9543 GLsizei height = static_cast<GLsizei>(c.height);
9544 GLsizei depth = static_cast<GLsizei>(c.depth);
9545 GLint border = static_cast<GLint>(c.border);
9546 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9547 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9548 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9549 const void* data = NULL;
9550 if (data_shm_id != 0 || data_shm_offset != 0) {
9551 data = GetSharedMemoryAs<const void*>(
9552 data_shm_id, data_shm_offset, image_size);
9553 if (!data) {
9554 return error::kOutOfBounds;
9557 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9558 depth, border, image_size, data);
9561 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9562 uint32 immediate_data_size, const void* cmd_data) {
9563 if (!unsafe_es3_apis_enabled())
9564 return error::kUnknownCommand;
9566 const gles2::cmds::CompressedTexImage3DBucket& c =
9567 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9568 GLenum target = static_cast<GLenum>(c.target);
9569 GLint level = static_cast<GLint>(c.level);
9570 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9571 GLsizei width = static_cast<GLsizei>(c.width);
9572 GLsizei height = static_cast<GLsizei>(c.height);
9573 GLsizei depth = static_cast<GLsizei>(c.depth);
9574 GLint border = static_cast<GLint>(c.border);
9575 Bucket* bucket = GetBucket(c.bucket_id);
9576 if (!bucket) {
9577 return error::kInvalidArguments;
9579 uint32 data_size = bucket->size();
9580 GLsizei imageSize = data_size;
9581 const void* data = bucket->GetData(0, data_size);
9582 if (!data) {
9583 return error::kInvalidArguments;
9585 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9586 depth, border, imageSize, data);
9589 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9590 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9591 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9592 GLsizei image_size, const void* data) {
9593 if (!validators_->texture_3_d_target.IsValid(target)) {
9594 LOCAL_SET_GL_ERROR(
9595 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9596 return;
9598 if (!validators_->compressed_texture_format.IsValid(format)) {
9599 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9600 "glCompressedTexSubImage3D", format, "format");
9601 return;
9603 if (width < 0 || height < 0 || depth < 0) {
9604 LOCAL_SET_GL_ERROR(
9605 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9606 return;
9608 if (image_size < 0) {
9609 LOCAL_SET_GL_ERROR(
9610 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9611 return;
9613 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9614 &state_, target);
9615 if (!texture_ref) {
9616 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9617 "unknown texture for target");
9618 return;
9620 Texture* texture = texture_ref->texture();
9621 GLenum type = 0, internal_format = 0;
9622 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9623 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9624 "level does not exist");
9625 return;
9627 if (internal_format != format) {
9628 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9629 "format does not match internal format");
9630 return;
9632 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9633 width, height, depth, type)) {
9634 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9635 "bad dimensions");
9636 return;
9638 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9639 width, height, depth, format,
9640 image_size) ||
9641 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9642 target, level, xoffset, yoffset,
9643 zoffset, width, height, depth,
9644 format, texture)) {
9645 return;
9648 // Note: There is no need to deal with texture cleared tracking here
9649 // because the validation above means you can only get here if the level
9650 // is already a matching compressed format and in that case
9651 // CompressedTexImage3D already cleared the texture.
9652 glCompressedTexSubImage3D(
9653 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9654 image_size, data);
9656 // This may be a slow command. Exit command processing to allow for
9657 // context preemption and GPU watchdog checks.
9658 ExitCommandProcessingEarly();
9661 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9662 uint32 immediate_data_size, const void* cmd_data) {
9663 if (!unsafe_es3_apis_enabled())
9664 return error::kUnknownCommand;
9665 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9666 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9667 GLenum target = static_cast<GLenum>(c.target);
9668 GLint level = static_cast<GLint>(c.level);
9669 GLint xoffset = static_cast<GLint>(c.xoffset);
9670 GLint yoffset = static_cast<GLint>(c.yoffset);
9671 GLint zoffset = static_cast<GLint>(c.zoffset);
9672 GLsizei width = static_cast<GLsizei>(c.width);
9673 GLsizei height = static_cast<GLsizei>(c.height);
9674 GLsizei depth = static_cast<GLsizei>(c.depth);
9675 GLenum format = static_cast<GLenum>(c.format);
9676 Bucket* bucket = GetBucket(c.bucket_id);
9677 if (!bucket) {
9678 return error::kInvalidArguments;
9680 uint32 data_size = bucket->size();
9681 GLsizei image_size = data_size;
9682 const void* data = bucket->GetData(0, data_size);
9683 if (!data) {
9684 return error::kInvalidArguments;
9686 DoCompressedTexSubImage3D(
9687 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9688 image_size, data);
9689 return error::kNoError;
9692 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9693 const void* cmd_data) {
9694 const gles2::cmds::TexImage2D& c =
9695 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9696 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9697 "width", c.width, "height", c.height);
9698 // Set as failed for now, but if it successed, this will be set to not failed.
9699 texture_state_.tex_image_failed = true;
9700 GLenum target = static_cast<GLenum>(c.target);
9701 GLint level = static_cast<GLint>(c.level);
9702 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9703 // for internalformat.
9704 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9705 GLsizei width = static_cast<GLsizei>(c.width);
9706 GLsizei height = static_cast<GLsizei>(c.height);
9707 GLint border = static_cast<GLint>(c.border);
9708 GLenum format = static_cast<GLenum>(c.format);
9709 GLenum type = static_cast<GLenum>(c.type);
9710 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9711 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9712 uint32 pixels_size;
9713 if (!GLES2Util::ComputeImageDataSizes(
9714 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9715 NULL, NULL)) {
9716 return error::kOutOfBounds;
9718 const void* pixels = NULL;
9719 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9720 pixels = GetSharedMemoryAs<const void*>(
9721 pixels_shm_id, pixels_shm_offset, pixels_size);
9722 if (!pixels) {
9723 return error::kOutOfBounds;
9727 // For testing only. Allows us to stress the ability to respond to OOM errors.
9728 if (workarounds().simulate_out_of_memory_on_large_textures &&
9729 (width * height >= 4096 * 4096)) {
9730 LOCAL_SET_GL_ERROR(
9731 GL_OUT_OF_MEMORY,
9732 "glTexImage2D", "synthetic out of memory");
9733 return error::kNoError;
9736 TextureManager::DoTexImageArguments args = {
9737 target, level, internal_format, width, height, 1, border, format, type,
9738 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
9739 texture_manager()->ValidateAndDoTexImage(
9740 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
9742 // This may be a slow command. Exit command processing to allow for
9743 // context preemption and GPU watchdog checks.
9744 ExitCommandProcessingEarly();
9745 return error::kNoError;
9748 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9749 const void* cmd_data) {
9750 if (!unsafe_es3_apis_enabled())
9751 return error::kUnknownCommand;
9753 const gles2::cmds::TexImage3D& c =
9754 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
9755 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9756 "widthXheight", c.width * c.height, "depth", c.depth);
9757 // Set as failed for now, but if it successed, this will be set to not failed.
9758 texture_state_.tex_image_failed = true;
9759 GLenum target = static_cast<GLenum>(c.target);
9760 GLint level = static_cast<GLint>(c.level);
9761 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9762 GLsizei width = static_cast<GLsizei>(c.width);
9763 GLsizei height = static_cast<GLsizei>(c.height);
9764 GLsizei depth = static_cast<GLsizei>(c.depth);
9765 GLint border = static_cast<GLint>(c.border);
9766 GLenum format = static_cast<GLenum>(c.format);
9767 GLenum type = static_cast<GLenum>(c.type);
9768 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9769 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9770 uint32 pixels_size;
9771 if (!GLES2Util::ComputeImageDataSizes(
9772 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
9773 NULL, NULL)) {
9774 return error::kOutOfBounds;
9776 const void* pixels = NULL;
9777 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9778 pixels = GetSharedMemoryAs<const void*>(
9779 pixels_shm_id, pixels_shm_offset, pixels_size);
9780 if (!pixels) {
9781 return error::kOutOfBounds;
9785 // For testing only. Allows us to stress the ability to respond to OOM errors.
9786 if (workarounds().simulate_out_of_memory_on_large_textures &&
9787 (width * height * depth >= 4096 * 4096)) {
9788 LOCAL_SET_GL_ERROR(
9789 GL_OUT_OF_MEMORY,
9790 "glTexImage3D", "synthetic out of memory");
9791 return error::kNoError;
9794 TextureManager::DoTexImageArguments args = {
9795 target, level, internal_format, width, height, depth, border, format, type,
9796 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
9797 texture_manager()->ValidateAndDoTexImage(
9798 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
9800 // This may be a slow command. Exit command processing to allow for
9801 // context preemption and GPU watchdog checks.
9802 ExitCommandProcessingEarly();
9803 return error::kNoError;
9806 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9807 GLenum target,
9808 GLint level,
9809 GLint xoffset,
9810 GLint yoffset,
9811 GLsizei width,
9812 GLsizei height,
9813 GLenum format,
9814 GLsizei image_size,
9815 const void * data) {
9816 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9817 &state_, target);
9818 if (!texture_ref) {
9819 LOCAL_SET_GL_ERROR(
9820 GL_INVALID_OPERATION,
9821 "glCompressedTexSubImage2D", "unknown texture for target");
9822 return;
9824 Texture* texture = texture_ref->texture();
9825 GLenum type = 0;
9826 GLenum internal_format = 0;
9827 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9828 LOCAL_SET_GL_ERROR(
9829 GL_INVALID_OPERATION,
9830 "glCompressedTexSubImage2D", "level does not exist.");
9831 return;
9833 if (internal_format != format) {
9834 LOCAL_SET_GL_ERROR(
9835 GL_INVALID_OPERATION,
9836 "glCompressedTexSubImage2D", "format does not match internal format.");
9837 return;
9839 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
9840 height, 1, type)) {
9841 LOCAL_SET_GL_ERROR(
9842 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
9843 return;
9846 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9847 width, height, 1, format, image_size) ||
9848 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
9849 target, level, xoffset, yoffset, 0,
9850 width, height, 1, format, texture)) {
9851 return;
9855 // Note: There is no need to deal with texture cleared tracking here
9856 // because the validation above means you can only get here if the level
9857 // is already a matching compressed format and in that case
9858 // CompressedTexImage2D already cleared the texture.
9859 glCompressedTexSubImage2D(
9860 target, level, xoffset, yoffset, width, height, format, image_size, data);
9862 // This may be a slow command. Exit command processing to allow for
9863 // context preemption and GPU watchdog checks.
9864 ExitCommandProcessingEarly();
9867 static void Clip(
9868 GLint start, GLint range, GLint sourceRange,
9869 GLint* out_start, GLint* out_range) {
9870 DCHECK(out_start);
9871 DCHECK(out_range);
9872 if (start < 0) {
9873 range += start;
9874 start = 0;
9876 GLint end = start + range;
9877 if (end > sourceRange) {
9878 range -= end - sourceRange;
9880 *out_start = start;
9881 *out_range = range;
9884 void GLES2DecoderImpl::DoCopyTexImage2D(
9885 GLenum target,
9886 GLint level,
9887 GLenum internal_format,
9888 GLint x,
9889 GLint y,
9890 GLsizei width,
9891 GLsizei height,
9892 GLint border) {
9893 DCHECK(!ShouldDeferReads());
9894 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9895 &state_, target);
9896 if (!texture_ref) {
9897 LOCAL_SET_GL_ERROR(
9898 GL_INVALID_OPERATION,
9899 "glCopyTexImage2D", "unknown texture for target");
9900 return;
9902 Texture* texture = texture_ref->texture();
9903 if (texture->IsImmutable()) {
9904 LOCAL_SET_GL_ERROR(
9905 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
9906 return;
9908 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9909 border != 0) {
9910 LOCAL_SET_GL_ERROR(
9911 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
9912 return;
9914 if (!texture_manager()->ValidateFormatAndTypeCombination(
9915 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
9916 GL_UNSIGNED_BYTE)) {
9917 return;
9920 // Check we have compatible formats.
9921 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9922 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9923 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
9925 if ((channels_needed & channels_exist) != channels_needed) {
9926 LOCAL_SET_GL_ERROR(
9927 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
9928 return;
9931 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9932 LOCAL_SET_GL_ERROR(
9933 GL_INVALID_OPERATION,
9934 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9935 return;
9938 uint32 estimated_size = 0;
9939 if (!GLES2Util::ComputeImageDataSizes(
9940 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
9941 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
9942 LOCAL_SET_GL_ERROR(
9943 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
9944 return;
9947 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9948 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
9949 return;
9952 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9953 return;
9956 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9957 LOCAL_SET_GL_ERROR(
9958 GL_INVALID_OPERATION,
9959 "glCopyTexImage2D", "source and destination textures are the same");
9960 return;
9963 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9964 return;
9967 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9968 ScopedResolvedFrameBufferBinder binder(this, false, true);
9969 gfx::Size size = GetBoundReadFrameBufferSize();
9971 if (texture->IsAttachedToFramebuffer()) {
9972 framebuffer_state_.clear_state_dirty = true;
9975 // Clip to size to source dimensions
9976 GLint copyX = 0;
9977 GLint copyY = 0;
9978 GLint copyWidth = 0;
9979 GLint copyHeight = 0;
9980 Clip(x, width, size.width(), &copyX, &copyWidth);
9981 Clip(y, height, size.height(), &copyY, &copyHeight);
9983 if (copyX != x ||
9984 copyY != y ||
9985 copyWidth != width ||
9986 copyHeight != height) {
9987 // some part was clipped so clear the texture.
9988 if (!ClearLevel(texture, target, level, internal_format, internal_format,
9989 GL_UNSIGNED_BYTE, width, height, texture->IsImmutable())) {
9990 LOCAL_SET_GL_ERROR(
9991 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
9992 return;
9994 if (copyHeight > 0 && copyWidth > 0) {
9995 GLint dx = copyX - x;
9996 GLint dy = copyY - y;
9997 GLint destX = dx;
9998 GLint destY = dy;
9999 ScopedModifyPixels modify(texture_ref);
10000 glCopyTexSubImage2D(target, level,
10001 destX, destY, copyX, copyY,
10002 copyWidth, copyHeight);
10004 } else {
10005 ScopedModifyPixels modify(texture_ref);
10006 glCopyTexImage2D(target, level, internal_format,
10007 copyX, copyY, copyWidth, copyHeight, border);
10009 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10010 if (error == GL_NO_ERROR) {
10011 texture_manager()->SetLevelInfo(
10012 texture_ref, target, level, internal_format, width, height, 1,
10013 border, internal_format, GL_UNSIGNED_BYTE, true);
10016 // This may be a slow command. Exit command processing to allow for
10017 // context preemption and GPU watchdog checks.
10018 ExitCommandProcessingEarly();
10021 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10022 GLenum target,
10023 GLint level,
10024 GLint xoffset,
10025 GLint yoffset,
10026 GLint x,
10027 GLint y,
10028 GLsizei width,
10029 GLsizei height) {
10030 DCHECK(!ShouldDeferReads());
10031 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10032 &state_, target);
10033 if (!texture_ref) {
10034 LOCAL_SET_GL_ERROR(
10035 GL_INVALID_OPERATION,
10036 "glCopyTexSubImage2D", "unknown texture for target");
10037 return;
10039 Texture* texture = texture_ref->texture();
10040 GLenum type = 0;
10041 GLenum format = 0;
10042 if (!texture->GetLevelType(target, level, &type, &format) ||
10043 !texture->ValidForTexture(
10044 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10045 LOCAL_SET_GL_ERROR(
10046 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10047 return;
10049 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10050 LOCAL_SET_GL_ERROR(
10051 GL_INVALID_OPERATION,
10052 "glCopyTexSubImage2D", "async upload pending for texture");
10053 return;
10056 // Check we have compatible formats.
10057 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10058 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10059 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10061 if (!channels_needed ||
10062 (channels_needed & channels_exist) != channels_needed) {
10063 LOCAL_SET_GL_ERROR(
10064 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10065 return;
10068 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10069 LOCAL_SET_GL_ERROR(
10070 GL_INVALID_OPERATION,
10071 "glCopySubImage2D", "can not be used with depth or stencil textures");
10072 return;
10075 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10076 return;
10079 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10080 LOCAL_SET_GL_ERROR(
10081 GL_INVALID_OPERATION,
10082 "glCopyTexSubImage2D", "source and destination textures are the same");
10083 return;
10086 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10087 return;
10090 ScopedResolvedFrameBufferBinder binder(this, false, true);
10091 gfx::Size size = GetBoundReadFrameBufferSize();
10092 GLint copyX = 0;
10093 GLint copyY = 0;
10094 GLint copyWidth = 0;
10095 GLint copyHeight = 0;
10096 Clip(x, width, size.width(), &copyX, &copyWidth);
10097 Clip(y, height, size.height(), &copyY, &copyHeight);
10099 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10100 height != size.height()) {
10101 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10102 level)) {
10103 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10104 "dimensions too big");
10105 return;
10107 } else {
10108 // Write all pixels in below.
10109 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10112 if (copyX != x ||
10113 copyY != y ||
10114 copyWidth != width ||
10115 copyHeight != height) {
10116 // some part was clipped so clear the sub rect.
10117 uint32 pixels_size = 0;
10118 if (!GLES2Util::ComputeImageDataSizes(
10119 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10120 NULL, NULL)) {
10121 LOCAL_SET_GL_ERROR(
10122 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10123 return;
10125 scoped_ptr<char[]> zero(new char[pixels_size]);
10126 memset(zero.get(), 0, pixels_size);
10127 ScopedModifyPixels modify(texture_ref);
10128 glTexSubImage2D(
10129 target, level, xoffset, yoffset, width, height,
10130 format, type, zero.get());
10133 if (copyHeight > 0 && copyWidth > 0) {
10134 GLint dx = copyX - x;
10135 GLint dy = copyY - y;
10136 GLint destX = xoffset + dx;
10137 GLint destY = yoffset + dy;
10138 ScopedModifyPixels modify(texture_ref);
10139 glCopyTexSubImage2D(target, level,
10140 destX, destY, copyX, copyY,
10141 copyWidth, copyHeight);
10144 // This may be a slow command. Exit command processing to allow for
10145 // context preemption and GPU watchdog checks.
10146 ExitCommandProcessingEarly();
10149 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10150 error::Error* error,
10151 const char* function_name,
10152 GLenum target,
10153 GLint level,
10154 GLint xoffset,
10155 GLint yoffset,
10156 GLsizei width,
10157 GLsizei height,
10158 GLenum format,
10159 GLenum type,
10160 const void * data) {
10161 (*error) = error::kNoError;
10162 if (!validators_->texture_target.IsValid(target)) {
10163 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10164 return false;
10166 if (width < 0) {
10167 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10168 return false;
10170 if (height < 0) {
10171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10172 return false;
10174 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10175 &state_, target);
10176 if (!texture_ref) {
10177 LOCAL_SET_GL_ERROR(
10178 GL_INVALID_OPERATION,
10179 function_name, "unknown texture for target");
10180 return false;
10182 Texture* texture = texture_ref->texture();
10183 GLenum current_type = 0;
10184 GLenum internal_format = 0;
10185 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10186 LOCAL_SET_GL_ERROR(
10187 GL_INVALID_OPERATION, function_name, "level does not exist.");
10188 return false;
10190 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10191 function_name, format, type, internal_format, level)) {
10192 return false;
10194 if (type != current_type) {
10195 LOCAL_SET_GL_ERROR(
10196 GL_INVALID_OPERATION,
10197 function_name, "type does not match type of texture.");
10198 return false;
10200 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10201 LOCAL_SET_GL_ERROR(
10202 GL_INVALID_OPERATION,
10203 function_name, "async upload pending for texture");
10204 return false;
10206 if (!texture->ValidForTexture(
10207 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10208 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10209 return false;
10211 if ((GLES2Util::GetChannelsForFormat(format) &
10212 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10213 LOCAL_SET_GL_ERROR(
10214 GL_INVALID_OPERATION,
10215 function_name, "can not supply data for depth or stencil textures");
10216 return false;
10218 if (data == NULL) {
10219 (*error) = error::kOutOfBounds;
10220 return false;
10222 return true;
10225 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10226 GLenum target,
10227 GLint level,
10228 GLint xoffset,
10229 GLint yoffset,
10230 GLsizei width,
10231 GLsizei height,
10232 GLenum format,
10233 GLenum type,
10234 const void * data) {
10235 error::Error error = error::kNoError;
10236 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10237 xoffset, yoffset, width, height, format, type, data)) {
10238 return error;
10240 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10241 &state_, target);
10242 Texture* texture = texture_ref->texture();
10243 GLsizei tex_width = 0;
10244 GLsizei tex_height = 0;
10245 bool ok = texture->GetLevelSize(
10246 target, level, &tex_width, &tex_height, nullptr);
10247 DCHECK(ok);
10248 if (xoffset != 0 || yoffset != 0 ||
10249 width != tex_width || height != tex_height) {
10250 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10251 target, level)) {
10252 LOCAL_SET_GL_ERROR(
10253 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
10254 return error::kNoError;
10256 ScopedTextureUploadTimer timer(&texture_state_);
10257 glTexSubImage2D(
10258 target, level, xoffset, yoffset, width, height, format, type, data);
10259 return error::kNoError;
10262 if (!texture_state_.texsubimage_faster_than_teximage &&
10263 !texture->IsImmutable() &&
10264 !texture->HasImages()) {
10265 ScopedTextureUploadTimer timer(&texture_state_);
10266 GLenum internal_format;
10267 GLenum tex_type;
10268 texture->GetLevelType(target, level, &tex_type, &internal_format);
10269 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10270 // to look it up.
10271 glTexImage2D(
10272 target, level, internal_format, width, height, 0, format, type, data);
10273 } else {
10274 ScopedTextureUploadTimer timer(&texture_state_);
10275 glTexSubImage2D(
10276 target, level, xoffset, yoffset, width, height, format, type, data);
10278 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10280 // This may be a slow command. Exit command processing to allow for
10281 // context preemption and GPU watchdog checks.
10282 ExitCommandProcessingEarly();
10283 return error::kNoError;
10286 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10287 const void* cmd_data) {
10288 const gles2::cmds::TexSubImage2D& c =
10289 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10290 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10291 "width", c.width, "height", c.height);
10292 GLboolean internal = static_cast<GLboolean>(c.internal);
10293 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10294 return error::kNoError;
10296 GLenum target = static_cast<GLenum>(c.target);
10297 GLint level = static_cast<GLint>(c.level);
10298 GLint xoffset = static_cast<GLint>(c.xoffset);
10299 GLint yoffset = static_cast<GLint>(c.yoffset);
10300 GLsizei width = static_cast<GLsizei>(c.width);
10301 GLsizei height = static_cast<GLsizei>(c.height);
10302 GLenum format = static_cast<GLenum>(c.format);
10303 GLenum type = static_cast<GLenum>(c.type);
10304 uint32 data_size;
10305 if (!GLES2Util::ComputeImageDataSizes(
10306 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10307 NULL, NULL)) {
10308 return error::kOutOfBounds;
10310 const void* pixels = GetSharedMemoryAs<const void*>(
10311 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10312 return DoTexSubImage2D(
10313 target, level, xoffset, yoffset, width, height, format, type, pixels);
10316 error::Error GLES2DecoderImpl::DoTexSubImage3D(
10317 GLenum target,
10318 GLint level,
10319 GLint xoffset,
10320 GLint yoffset,
10321 GLint zoffset,
10322 GLsizei width,
10323 GLsizei height,
10324 GLsizei depth,
10325 GLenum format,
10326 GLenum type,
10327 const void * data) {
10328 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10329 &state_, target);
10330 if (!texture_ref) {
10331 LOCAL_SET_GL_ERROR(
10332 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
10335 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10336 ScopedTextureUploadTimer timer(&texture_state_);
10337 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10338 depth, format, type, data);
10339 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10340 if (error == GL_NO_ERROR) {
10341 // TODO(zmo): This is not 100% correct because only part of the level
10342 // image is cleared.
10343 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10346 // This may be a slow command. Exit command processing to allow for
10347 // context preemption and GPU watchdog checks.
10348 ExitCommandProcessingEarly();
10349 return error::kNoError;
10352 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10353 const void* cmd_data) {
10354 if (!unsafe_es3_apis_enabled())
10355 return error::kUnknownCommand;
10357 const gles2::cmds::TexSubImage3D& c =
10358 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10359 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10360 "widthXheight", c.width * c.height, "depth", c.depth);
10361 GLboolean internal = static_cast<GLboolean>(c.internal);
10362 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10363 return error::kNoError;
10365 GLenum target = static_cast<GLenum>(c.target);
10366 GLint level = static_cast<GLint>(c.level);
10367 GLint xoffset = static_cast<GLint>(c.xoffset);
10368 GLint yoffset = static_cast<GLint>(c.yoffset);
10369 GLint zoffset = static_cast<GLint>(c.zoffset);
10370 GLsizei width = static_cast<GLsizei>(c.width);
10371 GLsizei height = static_cast<GLsizei>(c.height);
10372 GLsizei depth = static_cast<GLsizei>(c.depth);
10373 GLenum format = static_cast<GLenum>(c.format);
10374 GLenum type = static_cast<GLenum>(c.type);
10375 uint32 data_size;
10376 if (!GLES2Util::ComputeImageDataSizes(
10377 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10378 NULL, NULL)) {
10379 return error::kOutOfBounds;
10381 const void* pixels = GetSharedMemoryAs<const void*>(
10382 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10383 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
10384 height, depth, format, type, pixels);
10387 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10388 uint32 immediate_data_size,
10389 const void* cmd_data) {
10390 const gles2::cmds::GetVertexAttribPointerv& c =
10391 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10392 GLuint index = static_cast<GLuint>(c.index);
10393 GLenum pname = static_cast<GLenum>(c.pname);
10394 typedef cmds::GetVertexAttribPointerv::Result Result;
10395 Result* result = GetSharedMemoryAs<Result*>(
10396 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10397 if (!result) {
10398 return error::kOutOfBounds;
10400 // Check that the client initialized the result.
10401 if (result->size != 0) {
10402 return error::kInvalidArguments;
10404 if (!validators_->vertex_pointer.IsValid(pname)) {
10405 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10406 "glGetVertexAttribPointerv", pname, "pname");
10407 return error::kNoError;
10409 if (index >= group_->max_vertex_attribs()) {
10410 LOCAL_SET_GL_ERROR(
10411 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10412 return error::kNoError;
10414 result->SetNumResults(1);
10415 *result->GetData() =
10416 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10417 return error::kNoError;
10420 template <class T>
10421 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10422 GLint fake_location,
10423 uint32 shm_id,
10424 uint32 shm_offset,
10425 error::Error* error,
10426 GLint* real_location,
10427 GLuint* service_id,
10428 SizedResult<T>** result_pointer,
10429 GLenum* result_type,
10430 GLsizei* result_size) {
10431 DCHECK(error);
10432 DCHECK(service_id);
10433 DCHECK(result_pointer);
10434 DCHECK(result_type);
10435 DCHECK(result_size);
10436 DCHECK(real_location);
10437 *error = error::kNoError;
10438 // Make sure we have enough room for the result on failure.
10439 SizedResult<T>* result;
10440 result = GetSharedMemoryAs<SizedResult<T>*>(
10441 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10442 if (!result) {
10443 *error = error::kOutOfBounds;
10444 return false;
10446 *result_pointer = result;
10447 // Set the result size to 0 so the client does not have to check for success.
10448 result->SetNumResults(0);
10449 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10450 if (!program) {
10451 return false;
10453 if (!program->IsValid()) {
10454 // Program was not linked successfully. (ie, glLinkProgram)
10455 LOCAL_SET_GL_ERROR(
10456 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10457 return false;
10459 *service_id = program->service_id();
10460 GLint array_index = -1;
10461 const Program::UniformInfo* uniform_info =
10462 program->GetUniformInfoByFakeLocation(
10463 fake_location, real_location, &array_index);
10464 if (!uniform_info) {
10465 // No such location.
10466 LOCAL_SET_GL_ERROR(
10467 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10468 return false;
10470 GLenum type = uniform_info->type;
10471 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10472 if (num_elements == 0) {
10473 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10474 return false;
10476 result = GetSharedMemoryAs<SizedResult<T>*>(
10477 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10478 if (!result) {
10479 *error = error::kOutOfBounds;
10480 return false;
10482 result->SetNumResults(num_elements);
10483 *result_size = num_elements * sizeof(T);
10484 *result_type = type;
10485 return true;
10488 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10489 const void* cmd_data) {
10490 const gles2::cmds::GetUniformiv& c =
10491 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10492 GLuint program = c.program;
10493 GLint fake_location = c.location;
10494 GLuint service_id;
10495 GLenum result_type;
10496 GLsizei result_size;
10497 GLint real_location = -1;
10498 Error error;
10499 cmds::GetUniformiv::Result* result;
10500 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10501 c.params_shm_offset, &error, &real_location,
10502 &service_id, &result, &result_type,
10503 &result_size)) {
10504 glGetUniformiv(
10505 service_id, real_location, result->GetData());
10507 return error;
10510 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10511 const void* cmd_data) {
10512 if (!unsafe_es3_apis_enabled())
10513 return error::kUnknownCommand;
10515 const gles2::cmds::GetUniformuiv& c =
10516 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10517 GLuint program = c.program;
10518 GLint fake_location = c.location;
10519 GLuint service_id;
10520 GLenum result_type;
10521 GLsizei result_size;
10522 GLint real_location = -1;
10523 Error error;
10524 cmds::GetUniformuiv::Result* result;
10525 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10526 c.params_shm_offset, &error, &real_location,
10527 &service_id, &result, &result_type,
10528 &result_size)) {
10529 glGetUniformuiv(
10530 service_id, real_location, result->GetData());
10532 return error;
10535 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10536 const void* cmd_data) {
10537 const gles2::cmds::GetUniformfv& c =
10538 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10539 GLuint program = c.program;
10540 GLint fake_location = c.location;
10541 GLuint service_id;
10542 GLint real_location = -1;
10543 Error error;
10544 cmds::GetUniformfv::Result* result;
10545 GLenum result_type;
10546 GLsizei result_size;
10547 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10548 c.params_shm_offset, &error, &real_location,
10549 &service_id, &result, &result_type,
10550 &result_size)) {
10551 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10552 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10553 GLsizei num_values = result_size / sizeof(GLfloat);
10554 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10555 glGetUniformiv(service_id, real_location, temp.get());
10556 GLfloat* dst = result->GetData();
10557 for (GLsizei ii = 0; ii < num_values; ++ii) {
10558 dst[ii] = (temp[ii] != 0);
10560 } else {
10561 glGetUniformfv(service_id, real_location, result->GetData());
10564 return error;
10567 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10568 uint32 immediate_data_size,
10569 const void* cmd_data) {
10570 const gles2::cmds::GetShaderPrecisionFormat& c =
10571 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10572 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10573 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10574 typedef cmds::GetShaderPrecisionFormat::Result Result;
10575 Result* result = GetSharedMemoryAs<Result*>(
10576 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10577 if (!result) {
10578 return error::kOutOfBounds;
10580 // Check that the client initialized the result.
10581 if (result->success != 0) {
10582 return error::kInvalidArguments;
10584 if (!validators_->shader_type.IsValid(shader_type)) {
10585 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10586 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10587 return error::kNoError;
10589 if (!validators_->shader_precision.IsValid(precision_type)) {
10590 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10591 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10592 return error::kNoError;
10595 result->success = 1; // true
10597 GLint range[2] = { 0, 0 };
10598 GLint precision = 0;
10599 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10601 result->min_range = range[0];
10602 result->max_range = range[1];
10603 result->precision = precision;
10605 return error::kNoError;
10608 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10609 uint32 immediate_data_size,
10610 const void* cmd_data) {
10611 const gles2::cmds::GetAttachedShaders& c =
10612 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10613 uint32 result_size = c.result_size;
10614 GLuint program_id = static_cast<GLuint>(c.program);
10615 Program* program = GetProgramInfoNotShader(
10616 program_id, "glGetAttachedShaders");
10617 if (!program) {
10618 return error::kNoError;
10620 typedef cmds::GetAttachedShaders::Result Result;
10621 uint32 max_count = Result::ComputeMaxResults(result_size);
10622 Result* result = GetSharedMemoryAs<Result*>(
10623 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10624 if (!result) {
10625 return error::kOutOfBounds;
10627 // Check that the client initialized the result.
10628 if (result->size != 0) {
10629 return error::kInvalidArguments;
10631 GLsizei count = 0;
10632 glGetAttachedShaders(
10633 program->service_id(), max_count, &count, result->GetData());
10634 for (GLsizei ii = 0; ii < count; ++ii) {
10635 if (!shader_manager()->GetClientId(result->GetData()[ii],
10636 &result->GetData()[ii])) {
10637 NOTREACHED();
10638 return error::kGenericError;
10641 result->SetNumResults(count);
10642 return error::kNoError;
10645 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10646 uint32 immediate_data_size,
10647 const void* cmd_data) {
10648 const gles2::cmds::GetActiveUniform& c =
10649 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10650 GLuint program_id = c.program;
10651 GLuint index = c.index;
10652 uint32 name_bucket_id = c.name_bucket_id;
10653 typedef cmds::GetActiveUniform::Result Result;
10654 Result* result = GetSharedMemoryAs<Result*>(
10655 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10656 if (!result) {
10657 return error::kOutOfBounds;
10659 // Check that the client initialized the result.
10660 if (result->success != 0) {
10661 return error::kInvalidArguments;
10663 Program* program = GetProgramInfoNotShader(
10664 program_id, "glGetActiveUniform");
10665 if (!program) {
10666 return error::kNoError;
10668 const Program::UniformInfo* uniform_info =
10669 program->GetUniformInfo(index);
10670 if (!uniform_info) {
10671 LOCAL_SET_GL_ERROR(
10672 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10673 return error::kNoError;
10675 result->success = 1; // true.
10676 result->size = uniform_info->size;
10677 result->type = uniform_info->type;
10678 Bucket* bucket = CreateBucket(name_bucket_id);
10679 bucket->SetFromString(uniform_info->name.c_str());
10680 return error::kNoError;
10683 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10684 uint32 immediate_data_size, const void* cmd_data) {
10685 if (!unsafe_es3_apis_enabled())
10686 return error::kUnknownCommand;
10687 const gles2::cmds::GetActiveUniformBlockiv& c =
10688 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10689 GLuint program_id = c.program;
10690 GLuint index = static_cast<GLuint>(c.index);
10691 GLenum pname = static_cast<GLenum>(c.pname);
10692 Program* program = GetProgramInfoNotShader(
10693 program_id, "glGetActiveUniformBlockiv");
10694 if (!program) {
10695 return error::kNoError;
10697 GLuint service_id = program->service_id();
10698 GLint link_status = GL_FALSE;
10699 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10700 if (link_status != GL_TRUE) {
10701 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10702 "glGetActiveActiveUniformBlockiv", "program not linked");
10703 return error::kNoError;
10705 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10706 GLsizei num_values = 1;
10707 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10708 GLint num = 0;
10709 glGetActiveUniformBlockiv(
10710 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10711 GLenum error = glGetError();
10712 if (error != GL_NO_ERROR) {
10713 // Assume this will the same error if calling with pname.
10714 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10715 return error::kNoError;
10717 num_values = static_cast<GLsizei>(num);
10719 typedef cmds::GetActiveUniformBlockiv::Result Result;
10720 Result* result = GetSharedMemoryAs<Result*>(
10721 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
10722 GLint* params = result ? result->GetData() : NULL;
10723 if (params == NULL) {
10724 return error::kOutOfBounds;
10726 // Check that the client initialized the result.
10727 if (result->size != 0) {
10728 return error::kInvalidArguments;
10730 glGetActiveUniformBlockiv(service_id, index, pname, params);
10731 GLenum error = glGetError();
10732 if (error == GL_NO_ERROR) {
10733 result->SetNumResults(num_values);
10734 } else {
10735 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10737 return error::kNoError;
10740 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10741 uint32 immediate_data_size, const void* cmd_data) {
10742 if (!unsafe_es3_apis_enabled())
10743 return error::kUnknownCommand;
10744 const gles2::cmds::GetActiveUniformBlockName& c =
10745 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
10746 GLuint program_id = c.program;
10747 GLuint index = c.index;
10748 uint32 name_bucket_id = c.name_bucket_id;
10749 typedef cmds::GetActiveUniformBlockName::Result Result;
10750 Result* result = GetSharedMemoryAs<Result*>(
10751 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10752 if (!result) {
10753 return error::kOutOfBounds;
10755 // Check that the client initialized the result.
10756 if (*result != 0) {
10757 return error::kInvalidArguments;
10759 Program* program = GetProgramInfoNotShader(
10760 program_id, "glGetActiveUniformBlockName");
10761 if (!program) {
10762 return error::kNoError;
10764 GLuint service_id = program->service_id();
10765 GLint link_status = GL_FALSE;
10766 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10767 if (link_status != GL_TRUE) {
10768 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10769 "glGetActiveActiveUniformBlockName", "program not linked");
10770 return error::kNoError;
10772 GLint max_length = 0;
10773 glGetProgramiv(
10774 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
10775 // Increase one so &buffer[0] is always valid.
10776 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
10777 std::vector<char> buffer(buf_size);
10778 GLsizei length = 0;
10779 glGetActiveUniformBlockName(
10780 service_id, index, buf_size, &length, &buffer[0]);
10781 if (length == 0) {
10782 *result = 0;
10783 return error::kNoError;
10785 *result = 1;
10786 Bucket* bucket = CreateBucket(name_bucket_id);
10787 DCHECK_GT(buf_size, length);
10788 DCHECK_EQ(0, buffer[length]);
10789 bucket->SetFromString(&buffer[0]);
10790 return error::kNoError;
10793 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
10794 uint32 immediate_data_size, const void* cmd_data) {
10795 if (!unsafe_es3_apis_enabled())
10796 return error::kUnknownCommand;
10797 const gles2::cmds::GetActiveUniformsiv& c =
10798 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
10799 GLuint program_id = c.program;
10800 GLenum pname = static_cast<GLenum>(c.pname);
10801 Bucket* bucket = GetBucket(c.indices_bucket_id);
10802 if (!bucket) {
10803 return error::kInvalidArguments;
10805 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
10806 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
10807 typedef cmds::GetActiveUniformsiv::Result Result;
10808 Result* result = GetSharedMemoryAs<Result*>(
10809 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
10810 GLint* params = result ? result->GetData() : NULL;
10811 if (params == NULL) {
10812 return error::kOutOfBounds;
10814 // Check that the client initialized the result.
10815 if (result->size != 0) {
10816 return error::kInvalidArguments;
10818 Program* program = GetProgramInfoNotShader(
10819 program_id, "glGetActiveUniformsiv");
10820 if (!program) {
10821 return error::kNoError;
10823 GLuint service_id = program->service_id();
10824 GLint link_status = GL_FALSE;
10825 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10826 if (link_status != GL_TRUE) {
10827 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10828 "glGetActiveUniformsiv", "program not linked");
10829 return error::kNoError;
10831 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10832 glGetActiveUniformsiv(service_id, count, indices, pname, params);
10833 GLenum error = glGetError();
10834 if (error == GL_NO_ERROR) {
10835 result->SetNumResults(count);
10836 } else {
10837 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
10839 return error::kNoError;
10842 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
10843 const void* cmd_data) {
10844 const gles2::cmds::GetActiveAttrib& c =
10845 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
10846 GLuint program_id = c.program;
10847 GLuint index = c.index;
10848 uint32 name_bucket_id = c.name_bucket_id;
10849 typedef cmds::GetActiveAttrib::Result Result;
10850 Result* result = GetSharedMemoryAs<Result*>(
10851 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10852 if (!result) {
10853 return error::kOutOfBounds;
10855 // Check that the client initialized the result.
10856 if (result->success != 0) {
10857 return error::kInvalidArguments;
10859 Program* program = GetProgramInfoNotShader(
10860 program_id, "glGetActiveAttrib");
10861 if (!program) {
10862 return error::kNoError;
10864 const Program::VertexAttrib* attrib_info =
10865 program->GetAttribInfo(index);
10866 if (!attrib_info) {
10867 LOCAL_SET_GL_ERROR(
10868 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
10869 return error::kNoError;
10871 result->success = 1; // true.
10872 result->size = attrib_info->size;
10873 result->type = attrib_info->type;
10874 Bucket* bucket = CreateBucket(name_bucket_id);
10875 bucket->SetFromString(attrib_info->name.c_str());
10876 return error::kNoError;
10879 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
10880 const void* cmd_data) {
10881 #if 1 // No binary shader support.
10882 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
10883 return error::kNoError;
10884 #else
10885 GLsizei n = static_cast<GLsizei>(c.n);
10886 if (n < 0) {
10887 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
10888 return error::kNoError;
10890 GLsizei length = static_cast<GLsizei>(c.length);
10891 if (length < 0) {
10892 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
10893 return error::kNoError;
10895 uint32 data_size;
10896 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
10897 return error::kOutOfBounds;
10899 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
10900 c.shaders_shm_id, c.shaders_shm_offset, data_size);
10901 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
10902 const void* binary = GetSharedMemoryAs<const void*>(
10903 c.binary_shm_id, c.binary_shm_offset, length);
10904 if (shaders == NULL || binary == NULL) {
10905 return error::kOutOfBounds;
10907 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10908 for (GLsizei ii = 0; ii < n; ++ii) {
10909 Shader* shader = GetShader(shaders[ii]);
10910 if (!shader) {
10911 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
10912 return error::kNoError;
10914 service_ids[ii] = shader->service_id();
10916 // TODO(gman): call glShaderBinary
10917 return error::kNoError;
10918 #endif
10921 void GLES2DecoderImpl::DoSwapBuffers() {
10922 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
10924 int this_frame_number = frame_number_++;
10925 // TRACE_EVENT for gpu tests:
10926 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10927 TRACE_EVENT_SCOPE_THREAD,
10928 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10929 "width", (is_offscreen ? offscreen_size_.width() :
10930 surface_->GetSize().width()));
10931 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10932 "offscreen", is_offscreen,
10933 "frame", this_frame_number);
10935 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10938 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
10939 "gpu_toplevel", "SwapBuffer");
10941 bool is_tracing;
10942 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10943 &is_tracing);
10944 if (is_tracing) {
10945 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
10946 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
10947 is_offscreen ? offscreen_size_ : surface_->GetSize());
10950 // If offscreen then don't actually SwapBuffers to the display. Just copy
10951 // the rendered frame to another frame buffer.
10952 if (is_offscreen) {
10953 TRACE_EVENT2("gpu", "Offscreen",
10954 "width", offscreen_size_.width(), "height", offscreen_size_.height());
10955 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
10956 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10957 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10958 // fix this.
10959 if (workarounds().needs_offscreen_buffer_workaround) {
10960 offscreen_saved_frame_buffer_->Create();
10961 glFinish();
10964 // Allocate the offscreen saved color texture.
10965 DCHECK(offscreen_saved_color_format_);
10966 offscreen_saved_color_texture_->AllocateStorage(
10967 offscreen_size_, offscreen_saved_color_format_, false);
10969 offscreen_saved_frame_buffer_->AttachRenderTexture(
10970 offscreen_saved_color_texture_.get());
10971 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
10972 if (offscreen_saved_frame_buffer_->CheckStatus() !=
10973 GL_FRAMEBUFFER_COMPLETE) {
10974 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10975 << "because offscreen saved FBO was incomplete.";
10976 MarkContextLost(error::kUnknown);
10977 group_->LoseContexts(error::kUnknown);
10978 return;
10981 // Clear the offscreen color texture.
10982 // TODO(piman): Is this still necessary?
10984 ScopedFrameBufferBinder binder(this,
10985 offscreen_saved_frame_buffer_->id());
10986 glClearColor(0, 0, 0, 0);
10987 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
10988 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
10989 glClear(GL_COLOR_BUFFER_BIT);
10990 RestoreClearState();
10994 UpdateParentTextureInfo();
10997 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
10998 return;
10999 ScopedGLErrorSuppressor suppressor(
11000 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11002 if (IsOffscreenBufferMultisampled()) {
11003 // For multisampled buffers, resolve the frame buffer.
11004 ScopedResolvedFrameBufferBinder binder(this, true, false);
11005 } else {
11006 ScopedFrameBufferBinder binder(this,
11007 offscreen_target_frame_buffer_->id());
11009 if (offscreen_target_buffer_preserved_) {
11010 // Copy the target frame buffer to the saved offscreen texture.
11011 offscreen_saved_color_texture_->Copy(
11012 offscreen_saved_color_texture_->size(),
11013 offscreen_saved_color_format_);
11014 } else {
11015 // Flip the textures in the parent context via the texture manager.
11016 if (!!offscreen_saved_color_texture_info_.get())
11017 offscreen_saved_color_texture_info_->texture()->
11018 SetServiceId(offscreen_target_color_texture_->id());
11020 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11021 offscreen_target_frame_buffer_->AttachRenderTexture(
11022 offscreen_target_color_texture_.get());
11025 // Ensure the side effects of the copy are visible to the parent
11026 // context. There is no need to do this for ANGLE because it uses a
11027 // single D3D device for all contexts.
11028 if (!feature_info_->gl_version_info().is_angle)
11029 glFlush();
11031 } else {
11032 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11033 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11034 if (!CheckResetStatus()) {
11035 MarkContextLost(error::kUnknown);
11036 group_->LoseContexts(error::kUnknown);
11041 // This may be a slow command. Exit command processing to allow for
11042 // context preemption and GPU watchdog checks.
11043 ExitCommandProcessingEarly();
11046 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11047 context_->SetSwapInterval(interval);
11050 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11051 uint32 immediate_data_size,
11052 const void* cmd_data) {
11053 const gles2::cmds::EnableFeatureCHROMIUM& c =
11054 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11055 Bucket* bucket = GetBucket(c.bucket_id);
11056 if (!bucket || bucket->size() == 0) {
11057 return error::kInvalidArguments;
11059 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11060 Result* result = GetSharedMemoryAs<Result*>(
11061 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11062 if (!result) {
11063 return error::kOutOfBounds;
11065 // Check that the client initialized the result.
11066 if (*result != 0) {
11067 return error::kInvalidArguments;
11069 std::string feature_str;
11070 if (!bucket->GetAsString(&feature_str)) {
11071 return error::kInvalidArguments;
11074 // TODO(gman): make this some kind of table to function pointer thingy.
11075 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11076 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11077 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11078 buffer_manager()->set_allow_fixed_attribs(true);
11079 // TODO(gman): decide how to remove the need for this const_cast.
11080 // I could make validators_ non const but that seems bad as this is the only
11081 // place it is needed. I could make some special friend class of validators
11082 // just to allow this to set them. That seems silly. I could refactor this
11083 // code to use the extension mechanism or the initialization attributes to
11084 // turn this feature on. Given that the only real point of this is to make
11085 // the conformance tests pass and given that there is lots of real work that
11086 // needs to be done it seems like refactoring for one to one of those
11087 // methods is a very low priority.
11088 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11089 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
11090 force_webgl_glsl_validation_ = true;
11091 InitializeShaderTranslator();
11092 } else {
11093 return error::kNoError;
11096 *result = 1; // true.
11097 return error::kNoError;
11100 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11101 uint32 immediate_data_size,
11102 const void* cmd_data) {
11103 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11104 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11105 cmd_data);
11106 Bucket* bucket = CreateBucket(c.bucket_id);
11107 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11108 info->Initialize(disallowed_features_);
11109 bucket->SetFromString(info->extensions().c_str());
11110 return error::kNoError;
11113 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11114 uint32 immediate_data_size,
11115 const void* cmd_data) {
11116 const gles2::cmds::RequestExtensionCHROMIUM& c =
11117 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11118 Bucket* bucket = GetBucket(c.bucket_id);
11119 if (!bucket || bucket->size() == 0) {
11120 return error::kInvalidArguments;
11122 std::string feature_str;
11123 if (!bucket->GetAsString(&feature_str)) {
11124 return error::kInvalidArguments;
11127 bool desire_webgl_glsl_validation =
11128 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
11129 bool desire_standard_derivatives = false;
11130 bool desire_frag_depth = false;
11131 bool desire_draw_buffers = false;
11132 bool desire_shader_texture_lod = false;
11133 if (force_webgl_glsl_validation_) {
11134 desire_standard_derivatives =
11135 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11136 desire_frag_depth =
11137 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11138 desire_draw_buffers =
11139 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11140 desire_shader_texture_lod =
11141 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11144 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
11145 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11146 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11147 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
11148 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
11149 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11150 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11151 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11152 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11153 InitializeShaderTranslator();
11156 UpdateCapabilities();
11158 return error::kNoError;
11161 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11162 uint32 immediate_data_size,
11163 const void* cmd_data) {
11164 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11165 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11166 GLuint program_id = static_cast<GLuint>(c.program);
11167 uint32 bucket_id = c.bucket_id;
11168 Bucket* bucket = CreateBucket(bucket_id);
11169 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11170 Program* program = NULL;
11171 program = GetProgram(program_id);
11172 if (!program || !program->IsValid()) {
11173 return error::kNoError;
11175 program->GetProgramInfo(program_manager(), bucket);
11176 return error::kNoError;
11179 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11180 uint32 immediate_data_size, const void* cmd_data) {
11181 if (!unsafe_es3_apis_enabled())
11182 return error::kUnknownCommand;
11183 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11184 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11185 GLuint program_id = static_cast<GLuint>(c.program);
11186 uint32 bucket_id = c.bucket_id;
11187 Bucket* bucket = CreateBucket(bucket_id);
11188 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11189 Program* program = NULL;
11190 program = GetProgram(program_id);
11191 if (!program || !program->IsValid()) {
11192 return error::kNoError;
11194 program->GetUniformBlocks(bucket);
11195 return error::kNoError;
11198 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11199 uint32 immediate_data_size, const void* cmd_data) {
11200 if (!unsafe_es3_apis_enabled())
11201 return error::kUnknownCommand;
11202 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11203 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11204 GLuint program_id = static_cast<GLuint>(c.program);
11205 uint32 bucket_id = c.bucket_id;
11206 Bucket* bucket = CreateBucket(bucket_id);
11207 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11208 Program* program = NULL;
11209 program = GetProgram(program_id);
11210 if (!program || !program->IsValid()) {
11211 return error::kNoError;
11213 program->GetUniformsES3(bucket);
11214 return error::kNoError;
11217 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11218 uint32 immediate_data_size,
11219 const void* cmd_data) {
11220 if (!unsafe_es3_apis_enabled())
11221 return error::kUnknownCommand;
11222 const gles2::cmds::GetTransformFeedbackVarying& c =
11223 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11224 GLuint program_id = c.program;
11225 GLuint index = c.index;
11226 uint32 name_bucket_id = c.name_bucket_id;
11227 typedef cmds::GetTransformFeedbackVarying::Result Result;
11228 Result* result = GetSharedMemoryAs<Result*>(
11229 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11230 if (!result) {
11231 return error::kOutOfBounds;
11233 // Check that the client initialized the result.
11234 if (result->success != 0) {
11235 return error::kInvalidArguments;
11237 Program* program = GetProgramInfoNotShader(
11238 program_id, "glGetTransformFeedbackVarying");
11239 if (!program) {
11240 return error::kNoError;
11242 GLuint service_id = program->service_id();
11243 GLint link_status = GL_FALSE;
11244 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11245 if (link_status != GL_TRUE) {
11246 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11247 "glGetTransformFeedbackVarying", "program not linked");
11248 return error::kNoError;
11250 GLint max_length = 0;
11251 glGetProgramiv(
11252 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11253 max_length = std::max(1, max_length);
11254 std::vector<char> buffer(max_length);
11255 GLsizei length = 0;
11256 GLsizei size = 0;
11257 GLenum type = 0;
11258 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11259 glGetTransformFeedbackVarying(
11260 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11261 GLenum error = glGetError();
11262 if (error != GL_NO_ERROR) {
11263 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11264 return error::kNoError;
11266 result->success = 1; // true.
11267 result->size = static_cast<int32_t>(size);
11268 result->type = static_cast<uint32_t>(type);
11269 Bucket* bucket = CreateBucket(name_bucket_id);
11270 DCHECK(length >= 0 && length < max_length);
11271 buffer[length] = '\0'; // Just to be safe.
11272 bucket->SetFromString(&buffer[0]);
11273 return error::kNoError;
11276 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11277 uint32 immediate_data_size, const void* cmd_data) {
11278 if (!unsafe_es3_apis_enabled())
11279 return error::kUnknownCommand;
11280 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11281 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11282 cmd_data);
11283 GLuint program_id = static_cast<GLuint>(c.program);
11284 uint32 bucket_id = c.bucket_id;
11285 Bucket* bucket = CreateBucket(bucket_id);
11286 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11287 Program* program = NULL;
11288 program = GetProgram(program_id);
11289 if (!program || !program->IsValid()) {
11290 return error::kNoError;
11292 program->GetTransformFeedbackVaryings(bucket);
11293 return error::kNoError;
11296 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11297 return context_lost_reason_;
11300 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11301 GLenum reset_status) const {
11302 switch (reset_status) {
11303 case GL_NO_ERROR:
11304 // TODO(kbr): improve the precision of the error code in this case.
11305 // Consider delegating to context for error code if MakeCurrent fails.
11306 return error::kUnknown;
11307 case GL_GUILTY_CONTEXT_RESET_ARB:
11308 return error::kGuilty;
11309 case GL_INNOCENT_CONTEXT_RESET_ARB:
11310 return error::kInnocent;
11311 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11312 return error::kUnknown;
11315 NOTREACHED();
11316 return error::kUnknown;
11319 bool GLES2DecoderImpl::WasContextLost() const {
11320 return context_was_lost_;
11323 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11324 return WasContextLost() && reset_by_robustness_extension_;
11327 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11328 // Only lose the context once.
11329 if (WasContextLost())
11330 return;
11332 // Don't make GL calls in here, the context might not be current.
11333 context_lost_reason_ = reason;
11334 current_decoder_error_ = error::kLostContext;
11335 context_was_lost_ = true;
11337 // Work around issues with recovery by allowing a new GPU process to launch.
11338 if (workarounds().exit_on_context_lost && allow_exit_) {
11339 LOG(ERROR) << "Exiting GPU process because some drivers cannot recover"
11340 << " from problems.";
11341 #if defined(OS_WIN)
11342 base::win::SetShouldCrashOnProcessDetach(false);
11343 #endif
11344 exit(0);
11348 bool GLES2DecoderImpl::CheckResetStatus() {
11349 DCHECK(!WasContextLost());
11350 DCHECK(context_->IsCurrent(NULL));
11352 if (IsRobustnessSupported()) {
11353 // If the reason for the call was a GL error, we can try to determine the
11354 // reset status more accurately.
11355 GLenum driver_status = glGetGraphicsResetStatusARB();
11356 if (driver_status == GL_NO_ERROR)
11357 return false;
11359 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11360 << " context lost via ARB/EXT_robustness. Reset status = "
11361 << GLES2Util::GetStringEnum(driver_status);
11363 // Don't pretend we know which client was responsible.
11364 if (workarounds().use_virtualized_gl_contexts)
11365 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11367 switch (driver_status) {
11368 case GL_GUILTY_CONTEXT_RESET_ARB:
11369 MarkContextLost(error::kGuilty);
11370 break;
11371 case GL_INNOCENT_CONTEXT_RESET_ARB:
11372 MarkContextLost(error::kInnocent);
11373 break;
11374 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11375 MarkContextLost(error::kUnknown);
11376 break;
11377 default:
11378 NOTREACHED();
11379 return false;
11381 reset_by_robustness_extension_ = true;
11382 return true;
11384 return false;
11387 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11388 uint32 immediate_data_size,
11389 const void* cmd_data) {
11390 return error::kUnknownCommand;
11393 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11394 uint32 immediate_data_size,
11395 const void* cmd_data) {
11396 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11397 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11398 uint32 sync_point = c.sync_point;
11399 if (wait_sync_point_callback_.is_null())
11400 return error::kNoError;
11402 return wait_sync_point_callback_.Run(sync_point) ?
11403 error::kNoError : error::kDeferCommandUntilLater;
11406 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11407 uint32 immediate_data_size,
11408 const void* cmd_data) {
11409 if (surface_->DeferDraws())
11410 return error::kDeferCommandUntilLater;
11411 if (!surface_->SetBackbufferAllocation(false))
11412 return error::kLostContext;
11413 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11414 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11415 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11416 return error::kNoError;
11419 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11420 GLsizei n, const GLuint* client_ids) {
11421 for (GLsizei ii = 0; ii < n; ++ii) {
11422 if (query_manager_->GetQuery(client_ids[ii])) {
11423 return false;
11426 query_manager_->GenQueries(n, client_ids);
11427 return true;
11430 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11431 GLsizei n, const GLuint* client_ids) {
11432 for (GLsizei ii = 0; ii < n; ++ii) {
11433 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
11434 if (query && !query->IsDeleted()) {
11435 ContextState::QueryMap::iterator it =
11436 state_.current_queries.find(query->target());
11437 if (it != state_.current_queries.end())
11438 state_.current_queries.erase(it);
11440 query->Destroy(true);
11442 query_manager_->RemoveQuery(client_ids[ii]);
11446 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11447 if (query_manager_.get() == NULL) {
11448 return false;
11450 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11451 current_decoder_error_ = error::kOutOfBounds;
11453 return query_manager_->HavePendingQueries();
11456 // Note that if there are no pending readpixels right now,
11457 // this function will call the callback immediately.
11458 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11459 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11460 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11461 } else {
11462 callback.Run();
11466 void GLES2DecoderImpl::ProcessPendingReadPixels() {
11467 while (!pending_readpixel_fences_.empty() &&
11468 pending_readpixel_fences_.front()->fence->HasCompleted()) {
11469 std::vector<base::Closure> callbacks =
11470 pending_readpixel_fences_.front()->callbacks;
11471 pending_readpixel_fences_.pop();
11472 for (size_t i = 0; i < callbacks.size(); i++) {
11473 callbacks[i].Run();
11478 bool GLES2DecoderImpl::HasMoreIdleWork() {
11479 return !pending_readpixel_fences_.empty() ||
11480 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
11483 void GLES2DecoderImpl::PerformIdleWork() {
11484 ProcessPendingReadPixels();
11485 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11486 return;
11487 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11488 ProcessFinishedAsyncTransfers();
11491 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11492 const void* cmd_data) {
11493 const gles2::cmds::BeginQueryEXT& c =
11494 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11495 GLenum target = static_cast<GLenum>(c.target);
11496 GLuint client_id = static_cast<GLuint>(c.id);
11497 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11498 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11500 switch (target) {
11501 case GL_COMMANDS_ISSUED_CHROMIUM:
11502 case GL_LATENCY_QUERY_CHROMIUM:
11503 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11504 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11505 case GL_GET_ERROR_QUERY_CHROMIUM:
11506 break;
11507 case GL_COMMANDS_COMPLETED_CHROMIUM:
11508 if (!features().chromium_sync_query) {
11509 LOCAL_SET_GL_ERROR(
11510 GL_INVALID_OPERATION, "glBeginQueryEXT",
11511 "not enabled for commands completed queries");
11512 return error::kNoError;
11514 break;
11515 default:
11516 if (!features().occlusion_query_boolean) {
11517 LOCAL_SET_GL_ERROR(
11518 GL_INVALID_OPERATION, "glBeginQueryEXT",
11519 "not enabled for occlusion queries");
11520 return error::kNoError;
11522 break;
11525 if (state_.current_queries.find(target) != state_.current_queries.end()) {
11526 LOCAL_SET_GL_ERROR(
11527 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11528 return error::kNoError;
11531 if (client_id == 0) {
11532 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11533 return error::kNoError;
11536 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11537 if (!query) {
11538 if (!query_manager_->IsValidQuery(client_id)) {
11539 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11540 "glBeginQueryEXT",
11541 "id not made by glGenQueriesEXT");
11542 return error::kNoError;
11544 query = query_manager_->CreateQuery(
11545 target, client_id, sync_shm_id, sync_shm_offset);
11548 if (query->target() != target) {
11549 LOCAL_SET_GL_ERROR(
11550 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11551 return error::kNoError;
11552 } else if (query->shm_id() != sync_shm_id ||
11553 query->shm_offset() != sync_shm_offset) {
11554 DLOG(ERROR) << "Shared memory used by query not the same as before";
11555 return error::kInvalidArguments;
11558 if (!query_manager_->BeginQuery(query)) {
11559 return error::kOutOfBounds;
11562 state_.current_queries[target] = query;
11563 return error::kNoError;
11566 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11567 const void* cmd_data) {
11568 const gles2::cmds::EndQueryEXT& c =
11569 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11570 GLenum target = static_cast<GLenum>(c.target);
11571 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11572 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
11574 if (it == state_.current_queries.end()) {
11575 LOCAL_SET_GL_ERROR(
11576 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11577 return error::kNoError;
11580 QueryManager::Query* query = it->second.get();
11581 if (!query_manager_->EndQuery(query, submit_count)) {
11582 return error::kOutOfBounds;
11585 query_manager_->ProcessPendingTransferQueries();
11587 state_.current_queries.erase(it);
11588 return error::kNoError;
11591 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11592 GLsizei n, const GLuint* client_ids) {
11593 for (GLsizei ii = 0; ii < n; ++ii) {
11594 if (GetVertexAttribManager(client_ids[ii])) {
11595 return false;
11599 if (!features().native_vertex_array_object) {
11600 // Emulated VAO
11601 for (GLsizei ii = 0; ii < n; ++ii) {
11602 CreateVertexAttribManager(client_ids[ii], 0, true);
11604 } else {
11605 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11607 glGenVertexArraysOES(n, service_ids.get());
11608 for (GLsizei ii = 0; ii < n; ++ii) {
11609 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11613 return true;
11616 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11617 GLsizei n, const GLuint* client_ids) {
11618 for (GLsizei ii = 0; ii < n; ++ii) {
11619 VertexAttribManager* vao =
11620 GetVertexAttribManager(client_ids[ii]);
11621 if (vao && !vao->IsDeleted()) {
11622 if (state_.vertex_attrib_manager.get() == vao) {
11623 DoBindVertexArrayOES(0);
11625 RemoveVertexAttribManager(client_ids[ii]);
11630 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11631 VertexAttribManager* vao = NULL;
11632 if (client_id != 0) {
11633 vao = GetVertexAttribManager(client_id);
11634 if (!vao) {
11635 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11636 // only allows names that have been previously generated. As such, we do
11637 // not generate new names here.
11638 LOCAL_SET_GL_ERROR(
11639 GL_INVALID_OPERATION,
11640 "glBindVertexArrayOES", "bad vertex array id.");
11641 current_decoder_error_ = error::kNoError;
11642 return;
11644 } else {
11645 vao = state_.default_vertex_attrib_manager.get();
11648 // Only set the VAO state if it's changed
11649 if (state_.vertex_attrib_manager.get() != vao) {
11650 state_.vertex_attrib_manager = vao;
11651 if (!features().native_vertex_array_object) {
11652 EmulateVertexArrayState();
11653 } else {
11654 GLuint service_id = vao->service_id();
11655 glBindVertexArrayOES(service_id);
11660 // Used when OES_vertex_array_object isn't natively supported
11661 void GLES2DecoderImpl::EmulateVertexArrayState() {
11662 // Setup the Vertex attribute state
11663 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11664 RestoreStateForAttrib(vv, true);
11667 // Setup the element buffer
11668 Buffer* element_array_buffer =
11669 state_.vertex_attrib_manager->element_array_buffer();
11670 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11671 element_array_buffer ? element_array_buffer->service_id() : 0);
11674 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
11675 const VertexAttribManager* vao =
11676 GetVertexAttribManager(client_id);
11677 return vao && vao->IsValid() && !vao->IsDeleted();
11680 #if defined(OS_MACOSX)
11681 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
11682 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
11683 texture_id);
11684 if (it != texture_to_io_surface_map_.end()) {
11685 // Found a previous IOSurface bound to this texture; release it.
11686 IOSurfaceRef surface = it->second;
11687 CFRelease(surface);
11688 texture_to_io_surface_map_.erase(it);
11691 #endif
11693 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11694 GLenum target, GLsizei width, GLsizei height,
11695 GLuint io_surface_id, GLuint plane) {
11696 #if defined(OS_MACOSX)
11697 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
11698 LOCAL_SET_GL_ERROR(
11699 GL_INVALID_OPERATION,
11700 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11701 return;
11704 if (target != GL_TEXTURE_RECTANGLE_ARB) {
11705 // This might be supported in the future, and if we could require
11706 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11707 // could delete a lot of code. For now, perform strict validation so we
11708 // know what's going on.
11709 LOCAL_SET_GL_ERROR(
11710 GL_INVALID_OPERATION,
11711 "glTexImageIOSurface2DCHROMIUM",
11712 "requires TEXTURE_RECTANGLE_ARB target");
11713 return;
11716 // Default target might be conceptually valid, but disallow it to avoid
11717 // accidents.
11718 TextureRef* texture_ref =
11719 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11720 if (!texture_ref) {
11721 LOCAL_SET_GL_ERROR(
11722 GL_INVALID_OPERATION,
11723 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11724 return;
11727 // Look up the new IOSurface. Note that because of asynchrony
11728 // between processes this might fail; during live resizing the
11729 // plugin process might allocate and release an IOSurface before
11730 // this process gets a chance to look it up. Hold on to any old
11731 // IOSurface in this case.
11732 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
11733 if (!surface) {
11734 LOCAL_SET_GL_ERROR(
11735 GL_INVALID_OPERATION,
11736 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11737 return;
11740 // Release any IOSurface previously bound to this texture.
11741 ReleaseIOSurfaceForTexture(texture_ref->service_id());
11743 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11744 texture_to_io_surface_map_.insert(
11745 std::make_pair(texture_ref->service_id(), surface));
11747 CGLContextObj context =
11748 static_cast<CGLContextObj>(context_->GetHandle());
11750 CGLError err = CGLTexImageIOSurface2D(
11751 context,
11752 target,
11753 GL_RGBA,
11754 width,
11755 height,
11756 GL_BGRA,
11757 GL_UNSIGNED_INT_8_8_8_8_REV,
11758 surface,
11759 plane);
11761 if (err != kCGLNoError) {
11762 LOCAL_SET_GL_ERROR(
11763 GL_INVALID_OPERATION,
11764 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11765 return;
11768 texture_manager()->SetLevelInfo(
11769 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
11770 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
11772 #else
11773 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11774 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11775 #endif
11778 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
11779 switch (internalformat) {
11780 case GL_RGB565:
11781 return GL_RGB;
11782 case GL_RGBA4:
11783 return GL_RGBA;
11784 case GL_RGB5_A1:
11785 return GL_RGBA;
11786 case GL_RGB8_OES:
11787 return GL_RGB;
11788 case GL_RGBA8_OES:
11789 return GL_RGBA;
11790 case GL_LUMINANCE8_ALPHA8_EXT:
11791 return GL_LUMINANCE_ALPHA;
11792 case GL_LUMINANCE8_EXT:
11793 return GL_LUMINANCE;
11794 case GL_ALPHA8_EXT:
11795 return GL_ALPHA;
11796 case GL_RGBA32F_EXT:
11797 return GL_RGBA;
11798 case GL_RGB32F_EXT:
11799 return GL_RGB;
11800 case GL_ALPHA32F_EXT:
11801 return GL_ALPHA;
11802 case GL_LUMINANCE32F_EXT:
11803 return GL_LUMINANCE;
11804 case GL_LUMINANCE_ALPHA32F_EXT:
11805 return GL_LUMINANCE_ALPHA;
11806 case GL_RGBA16F_EXT:
11807 return GL_RGBA;
11808 case GL_RGB16F_EXT:
11809 return GL_RGB;
11810 case GL_ALPHA16F_EXT:
11811 return GL_ALPHA;
11812 case GL_LUMINANCE16F_EXT:
11813 return GL_LUMINANCE;
11814 case GL_LUMINANCE_ALPHA16F_EXT:
11815 return GL_LUMINANCE_ALPHA;
11816 case GL_BGRA8_EXT:
11817 return GL_BGRA_EXT;
11818 case GL_SRGB8_ALPHA8_EXT:
11819 return GL_SRGB_ALPHA_EXT;
11820 default:
11821 return GL_NONE;
11825 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11826 const char* function_name,
11827 GLenum target,
11828 TextureRef* source_texture_ref,
11829 TextureRef* dest_texture_ref,
11830 GLenum dest_internal_format) {
11831 if (!source_texture_ref || !dest_texture_ref) {
11832 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
11833 return false;
11836 if (GL_TEXTURE_2D != target) {
11837 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11838 "invalid texture target");
11839 return false;
11842 Texture* source_texture = source_texture_ref->texture();
11843 Texture* dest_texture = dest_texture_ref->texture();
11844 if (source_texture == dest_texture) {
11845 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11846 "source and destination textures are the same");
11847 return false;
11850 if (dest_texture->target() != GL_TEXTURE_2D ||
11851 (source_texture->target() != GL_TEXTURE_2D &&
11852 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
11853 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
11854 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
11855 "invalid texture target binding");
11856 return false;
11859 GLenum source_type = 0;
11860 GLenum source_internal_format = 0;
11861 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
11862 &source_internal_format);
11864 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11865 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11866 // renderable on some platforms.
11867 bool valid_dest_format = dest_internal_format == GL_RGB ||
11868 dest_internal_format == GL_RGBA ||
11869 dest_internal_format == GL_BGRA_EXT;
11870 bool valid_source_format = source_internal_format == GL_ALPHA ||
11871 source_internal_format == GL_RGB ||
11872 source_internal_format == GL_RGBA ||
11873 source_internal_format == GL_LUMINANCE ||
11874 source_internal_format == GL_LUMINANCE_ALPHA ||
11875 source_internal_format == GL_BGRA_EXT;
11876 if (!valid_source_format || !valid_dest_format) {
11877 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
11878 "invalid internal format");
11879 return false;
11881 return true;
11884 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target,
11885 GLuint source_id,
11886 GLuint dest_id,
11887 GLenum internal_format,
11888 GLenum dest_type) {
11889 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11891 TextureRef* source_texture_ref = GetTexture(source_id);
11892 TextureRef* dest_texture_ref = GetTexture(dest_id);
11893 Texture* source_texture = source_texture_ref->texture();
11894 Texture* dest_texture = dest_texture_ref->texture();
11895 int source_width = 0;
11896 int source_height = 0;
11897 gfx::GLImage* image =
11898 source_texture->GetLevelImage(source_texture->target(), 0);
11899 if (image) {
11900 gfx::Size size = image->GetSize();
11901 source_width = size.width();
11902 source_height = size.height();
11903 if (source_width <= 0 || source_height <= 0) {
11904 LOCAL_SET_GL_ERROR(
11905 GL_INVALID_VALUE,
11906 "glCopyTextureChromium", "invalid image size");
11907 return;
11909 } else {
11910 if (!source_texture->GetLevelSize(source_texture->target(), 0,
11911 &source_width, &source_height, nullptr)) {
11912 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
11913 "glCopyTextureChromium",
11914 "source texture has no level 0");
11915 return;
11918 // Check that this type of texture is allowed.
11919 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
11920 source_width, source_height, 1)) {
11921 LOCAL_SET_GL_ERROR(
11922 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
11923 return;
11927 GLenum source_type = 0;
11928 GLenum source_internal_format = 0;
11929 source_texture->GetLevelType(
11930 source_texture->target(), 0, &source_type, &source_internal_format);
11932 if (dest_texture->IsImmutable()) {
11933 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
11934 "texture is immutable");
11935 return;
11938 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
11939 source_texture_ref, dest_texture_ref,
11940 internal_format)) {
11941 return;
11944 // Clear the source texture if necessary.
11945 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
11946 source_texture->target(), 0)) {
11947 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
11948 "dimensions too big");
11949 return;
11952 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11953 // needed because it takes 10s of milliseconds to initialize.
11954 if (!copy_texture_CHROMIUM_.get()) {
11955 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11956 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
11957 copy_texture_CHROMIUM_->Initialize(this);
11958 RestoreCurrentFramebufferBindings();
11959 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
11960 return;
11963 GLenum dest_type_previous = dest_type;
11964 GLenum dest_internal_format = internal_format;
11965 int dest_width = 0;
11966 int dest_height = 0;
11967 bool dest_level_defined = dest_texture->GetLevelSize(
11968 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
11970 if (dest_level_defined) {
11971 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
11972 &dest_internal_format);
11975 // Resize the destination texture to the dimensions of the source texture.
11976 if (!dest_level_defined || dest_width != source_width ||
11977 dest_height != source_height ||
11978 dest_internal_format != internal_format ||
11979 dest_type_previous != dest_type) {
11980 // Ensure that the glTexImage2D succeeds.
11981 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11982 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
11983 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
11984 0, internal_format, dest_type, NULL);
11985 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11986 if (error != GL_NO_ERROR) {
11987 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
11988 return;
11991 texture_manager()->SetLevelInfo(
11992 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
11993 source_height, 1, 0, internal_format, dest_type, true);
11994 } else {
11995 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
11996 true);
11999 ScopedModifyPixels modify(dest_texture_ref);
12001 // Try using GLImage::CopyTexSubImage when possible.
12002 bool unpack_premultiply_alpha_change =
12003 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
12004 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) {
12005 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12006 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12007 gfx::Rect(0, 0, source_width, source_height))) {
12008 return;
12012 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12014 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12015 // before presenting.
12016 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12017 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12018 // instead of using kIdentityMatrix crbug.com/226218.
12019 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12020 this, source_texture->target(), source_texture->service_id(),
12021 dest_texture->service_id(), source_width, source_height, unpack_flip_y_,
12022 unpack_premultiply_alpha_, unpack_unpremultiply_alpha_,
12023 kIdentityMatrix);
12024 } else {
12025 copy_texture_CHROMIUM_->DoCopyTexture(
12026 this, source_texture->target(), source_texture->service_id(),
12027 source_internal_format, dest_texture->service_id(), internal_format,
12028 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
12029 unpack_unpremultiply_alpha_);
12032 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12035 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target,
12036 GLuint source_id,
12037 GLuint dest_id,
12038 GLint xoffset,
12039 GLint yoffset,
12040 GLint x,
12041 GLint y,
12042 GLsizei width,
12043 GLsizei height) {
12044 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12046 TextureRef* source_texture_ref = GetTexture(source_id);
12047 TextureRef* dest_texture_ref = GetTexture(dest_id);
12048 Texture* source_texture = source_texture_ref->texture();
12049 Texture* dest_texture = dest_texture_ref->texture();
12050 int source_width = 0;
12051 int source_height = 0;
12052 gfx::GLImage* image =
12053 source_texture->GetLevelImage(source_texture->target(), 0);
12054 if (image) {
12055 gfx::Size size = image->GetSize();
12056 source_width = size.width();
12057 source_height = size.height();
12058 if (source_width <= 0 || source_height <= 0) {
12059 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12060 "invalid image size");
12061 return;
12063 } else {
12064 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12065 &source_width, &source_height, nullptr)) {
12066 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12067 "source texture has no level 0");
12068 return;
12071 // Check that this type of texture is allowed.
12072 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12073 source_width, source_height, 1)) {
12074 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12075 "source texture bad dimensions");
12076 return;
12080 GLenum source_type = 0;
12081 GLenum source_internal_format = 0;
12082 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12083 &source_internal_format);
12084 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12085 width, height, 1, source_type)) {
12086 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12087 "source texture bad dimensions.");
12088 return;
12091 GLenum dest_type = 0;
12092 GLenum dest_internal_format = 0;
12093 bool dest_level_defined = dest_texture->GetLevelType(
12094 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12095 if (!dest_level_defined) {
12096 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
12097 "destination texture is not defined");
12098 return;
12100 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12101 yoffset, 0, width, height, 1, dest_type)) {
12102 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12103 "destination texture bad dimensions.");
12104 return;
12107 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
12108 source_texture_ref, dest_texture_ref,
12109 dest_internal_format)) {
12110 return;
12113 // Clear the source texture if necessary.
12114 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12115 source_texture->target(), 0)) {
12116 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12117 "source texture dimensions too big");
12118 return;
12121 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12122 // needed because it takes 10s of milliseconds to initialize.
12123 if (!copy_texture_CHROMIUM_.get()) {
12124 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12125 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12126 copy_texture_CHROMIUM_->Initialize(this);
12127 RestoreCurrentFramebufferBindings();
12128 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
12129 return;
12132 int dest_width = 0;
12133 int dest_height = 0;
12134 bool ok = dest_texture->GetLevelSize(
12135 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12136 DCHECK(ok);
12137 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12138 height != dest_height) {
12139 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12140 0)) {
12141 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12142 "destination texture dimensions too big");
12143 return;
12145 } else {
12146 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12147 true);
12150 ScopedModifyPixels modify(dest_texture_ref);
12152 // Try using GLImage::CopyTexSubImage when possible.
12153 bool unpack_premultiply_alpha_change =
12154 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
12155 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change) {
12156 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12157 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12158 gfx::Rect(x, y, width, height))) {
12159 return;
12163 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12165 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12166 // crbug.com/226218.
12167 copy_texture_CHROMIUM_->DoCopySubTexture(
12168 this, source_texture->target(), source_texture->service_id(),
12169 source_internal_format, dest_texture->service_id(), dest_internal_format,
12170 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
12171 source_width, source_height, unpack_flip_y_, unpack_premultiply_alpha_,
12172 unpack_unpremultiply_alpha_);
12174 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12177 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
12178 switch (internalformat) {
12179 case GL_RGB565:
12180 return GL_UNSIGNED_SHORT_5_6_5;
12181 case GL_RGBA4:
12182 return GL_UNSIGNED_SHORT_4_4_4_4;
12183 case GL_RGB5_A1:
12184 return GL_UNSIGNED_SHORT_5_5_5_1;
12185 case GL_RGB8_OES:
12186 return GL_UNSIGNED_BYTE;
12187 case GL_RGBA8_OES:
12188 return GL_UNSIGNED_BYTE;
12189 case GL_LUMINANCE8_ALPHA8_EXT:
12190 return GL_UNSIGNED_BYTE;
12191 case GL_LUMINANCE8_EXT:
12192 return GL_UNSIGNED_BYTE;
12193 case GL_ALPHA8_EXT:
12194 return GL_UNSIGNED_BYTE;
12195 case GL_RGBA32F_EXT:
12196 return GL_FLOAT;
12197 case GL_RGB32F_EXT:
12198 return GL_FLOAT;
12199 case GL_ALPHA32F_EXT:
12200 return GL_FLOAT;
12201 case GL_LUMINANCE32F_EXT:
12202 return GL_FLOAT;
12203 case GL_LUMINANCE_ALPHA32F_EXT:
12204 return GL_FLOAT;
12205 case GL_RGBA16F_EXT:
12206 return GL_HALF_FLOAT_OES;
12207 case GL_RGB16F_EXT:
12208 return GL_HALF_FLOAT_OES;
12209 case GL_ALPHA16F_EXT:
12210 return GL_HALF_FLOAT_OES;
12211 case GL_LUMINANCE16F_EXT:
12212 return GL_HALF_FLOAT_OES;
12213 case GL_LUMINANCE_ALPHA16F_EXT:
12214 return GL_HALF_FLOAT_OES;
12215 case GL_BGRA8_EXT:
12216 return GL_UNSIGNED_BYTE;
12217 default:
12218 return GL_NONE;
12222 void GLES2DecoderImpl::DoTexStorage2DEXT(
12223 GLenum target,
12224 GLint levels,
12225 GLenum internal_format,
12226 GLsizei width,
12227 GLsizei height) {
12228 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12229 "width", width, "height", height);
12230 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
12231 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
12232 LOCAL_SET_GL_ERROR(
12233 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
12234 return;
12236 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12237 &state_, target);
12238 if (!texture_ref) {
12239 LOCAL_SET_GL_ERROR(
12240 GL_INVALID_OPERATION,
12241 "glTexStorage2DEXT", "unknown texture for target");
12242 return;
12244 Texture* texture = texture_ref->texture();
12245 if (texture->IsAttachedToFramebuffer()) {
12246 framebuffer_state_.clear_state_dirty = true;
12248 if (texture->IsImmutable()) {
12249 LOCAL_SET_GL_ERROR(
12250 GL_INVALID_OPERATION,
12251 "glTexStorage2DEXT", "texture is immutable");
12252 return;
12255 GLenum format = ExtractFormatFromStorageFormat(internal_format);
12256 GLenum type = ExtractTypeFromStorageFormat(internal_format);
12259 GLsizei level_width = width;
12260 GLsizei level_height = height;
12261 uint32 estimated_size = 0;
12262 for (int ii = 0; ii < levels; ++ii) {
12263 uint32 level_size = 0;
12264 if (!GLES2Util::ComputeImageDataSizes(
12265 level_width, level_height, 1, format, type, state_.unpack_alignment,
12266 &estimated_size, NULL, NULL) ||
12267 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
12268 LOCAL_SET_GL_ERROR(
12269 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
12270 return;
12272 level_width = std::max(1, level_width >> 1);
12273 level_height = std::max(1, level_height >> 1);
12275 if (!EnsureGPUMemoryAvailable(estimated_size)) {
12276 LOCAL_SET_GL_ERROR(
12277 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
12278 return;
12282 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12283 glTexStorage2DEXT(target, levels, internal_format, width, height);
12284 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12285 if (error == GL_NO_ERROR) {
12286 GLsizei level_width = width;
12287 GLsizei level_height = height;
12288 for (int ii = 0; ii < levels; ++ii) {
12289 texture_manager()->SetLevelInfo(
12290 texture_ref, target, ii, format,
12291 level_width, level_height, 1, 0, format, type, false);
12292 level_width = std::max(1, level_width >> 1);
12293 level_height = std::max(1, level_height >> 1);
12295 texture->SetImmutable(true);
12299 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12300 uint32 immediate_data_size,
12301 const void* cmd_data) {
12302 return error::kUnknownCommand;
12305 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
12306 const GLbyte* data) {
12307 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12308 "context", logger_.GetLogPrefix(),
12309 "mailbox[0]", static_cast<unsigned char>(data[0]));
12311 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
12312 &state_, target);
12313 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
12316 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
12317 GLenum target, const GLbyte* data) {
12318 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12319 "context", logger_.GetLogPrefix(),
12320 "mailbox[0]", static_cast<unsigned char>(data[0]));
12322 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
12323 target, data);
12326 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
12327 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
12328 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12329 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
12330 "mailbox that was not generated by "
12331 "GenMailboxCHROMIUM.";
12333 if (!texture_ref) {
12334 LOCAL_SET_GL_ERROR(
12335 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
12336 return;
12339 Texture* produced = texture_manager()->Produce(texture_ref);
12340 if (!produced) {
12341 LOCAL_SET_GL_ERROR(
12342 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
12343 return;
12346 if (produced->target() != target) {
12347 LOCAL_SET_GL_ERROR(
12348 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
12349 return;
12352 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
12355 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
12356 const GLbyte* data) {
12357 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
12358 "context", logger_.GetLogPrefix(),
12359 "mailbox[0]", static_cast<unsigned char>(data[0]));
12360 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12361 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12362 "mailbox that was not generated by "
12363 "GenMailboxCHROMIUM.";
12365 scoped_refptr<TextureRef> texture_ref =
12366 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12367 if (!texture_ref.get()) {
12368 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12369 "glConsumeTextureCHROMIUM",
12370 "unknown texture for target");
12371 return;
12373 GLuint client_id = texture_ref->client_id();
12374 if (!client_id) {
12375 LOCAL_SET_GL_ERROR(
12376 GL_INVALID_OPERATION,
12377 "glConsumeTextureCHROMIUM", "unknown texture for target");
12378 return;
12380 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12381 if (!texture) {
12382 LOCAL_SET_GL_ERROR(
12383 GL_INVALID_OPERATION,
12384 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12385 return;
12387 if (texture->target() != target) {
12388 LOCAL_SET_GL_ERROR(
12389 GL_INVALID_OPERATION,
12390 "glConsumeTextureCHROMIUM", "invalid target");
12391 return;
12394 DeleteTexturesHelper(1, &client_id);
12395 texture_ref = texture_manager()->Consume(client_id, texture);
12396 glBindTexture(target, texture_ref->service_id());
12398 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
12399 unit.bind_target = target;
12400 switch (target) {
12401 case GL_TEXTURE_2D:
12402 unit.bound_texture_2d = texture_ref;
12403 break;
12404 case GL_TEXTURE_CUBE_MAP:
12405 unit.bound_texture_cube_map = texture_ref;
12406 break;
12407 case GL_TEXTURE_EXTERNAL_OES:
12408 unit.bound_texture_external_oes = texture_ref;
12409 break;
12410 case GL_TEXTURE_RECTANGLE_ARB:
12411 unit.bound_texture_rectangle_arb = texture_ref;
12412 break;
12413 default:
12414 NOTREACHED(); // Validation should prevent us getting here.
12415 break;
12419 void GLES2DecoderImpl::EnsureTextureForClientId(
12420 GLenum target,
12421 GLuint client_id) {
12422 TextureRef* texture_ref = GetTexture(client_id);
12423 if (!texture_ref) {
12424 GLuint service_id;
12425 glGenTextures(1, &service_id);
12426 DCHECK_NE(0u, service_id);
12427 texture_ref = CreateTexture(client_id, service_id);
12428 texture_manager()->SetTarget(texture_ref, target);
12429 glBindTexture(target, service_id);
12430 RestoreCurrentTextureBindings(&state_, target);
12434 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
12435 // provided is associated with a service_id/TextureRef for consistency, even if
12436 // the resulting texture is incomplete.
12437 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
12438 uint32_t immediate_data_size,
12439 const void* cmd_data) {
12440 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
12441 *static_cast<
12442 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
12443 cmd_data);
12444 GLenum target = static_cast<GLenum>(c.target);
12445 uint32_t data_size;
12446 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
12447 return error::kOutOfBounds;
12449 if (data_size > immediate_data_size) {
12450 return error::kOutOfBounds;
12452 const GLbyte* mailbox =
12453 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
12454 if (!validators_->texture_bind_target.IsValid(target)) {
12455 LOCAL_SET_GL_ERROR_INVALID_ENUM(
12456 "glCreateAndConsumeTextureCHROMIUM", target, "target");
12457 return error::kNoError;
12459 if (mailbox == NULL) {
12460 return error::kOutOfBounds;
12462 uint32_t client_id = c.client_id;
12463 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
12464 return error::kNoError;
12467 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
12468 const GLbyte* data, GLuint client_id) {
12469 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
12470 "context", logger_.GetLogPrefix(),
12471 "mailbox[0]", static_cast<unsigned char>(data[0]));
12472 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
12473 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
12474 "passed a mailbox that was not "
12475 "generated by GenMailboxCHROMIUM.";
12477 TextureRef* texture_ref = GetTexture(client_id);
12478 if (texture_ref) {
12479 // No need to call EnsureTextureForClientId here, the client_id already has
12480 // an associated texture.
12481 LOCAL_SET_GL_ERROR(
12482 GL_INVALID_OPERATION,
12483 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
12484 return;
12486 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
12487 if (!texture) {
12488 EnsureTextureForClientId(target, client_id);
12489 LOCAL_SET_GL_ERROR(
12490 GL_INVALID_OPERATION,
12491 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
12492 return;
12495 if (texture->target() != target) {
12496 EnsureTextureForClientId(target, client_id);
12497 LOCAL_SET_GL_ERROR(
12498 GL_INVALID_OPERATION,
12499 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
12500 return;
12503 texture_ref = texture_manager()->Consume(client_id, texture);
12506 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
12507 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
12508 return valuebuffer && valuebuffer->IsValid();
12511 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
12512 GLuint client_id) {
12513 Valuebuffer* valuebuffer = NULL;
12514 if (client_id != 0) {
12515 valuebuffer = GetValuebuffer(client_id);
12516 if (!valuebuffer) {
12517 if (!group_->bind_generates_resource()) {
12518 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
12519 "id not generated by glBindValuebufferCHROMIUM");
12520 return;
12523 // It's a new id so make a valuebuffer for it.
12524 CreateValuebuffer(client_id);
12525 valuebuffer = GetValuebuffer(client_id);
12527 valuebuffer->MarkAsValid();
12529 state_.bound_valuebuffer = valuebuffer;
12532 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
12533 GLenum subscription) {
12534 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
12535 return;
12537 state_.bound_valuebuffer.get()->AddSubscription(subscription);
12540 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
12541 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
12542 return;
12544 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
12547 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
12548 GLenum target,
12549 GLenum subscription) {
12550 if (!CheckCurrentValuebufferForSubscription(
12551 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
12552 return;
12554 if (!CheckSubscriptionTarget(location, subscription,
12555 "glPopulateSubscribedValuesCHROMIUM")) {
12556 return;
12558 const ValueState* state =
12559 state_.bound_valuebuffer.get()->GetState(subscription);
12560 if (state) {
12561 switch (subscription) {
12562 case GL_MOUSE_POSITION_CHROMIUM:
12563 DoUniform2iv(location, 1, state->int_value);
12564 break;
12565 default:
12566 NOTREACHED() << "Unhandled uniform subscription target "
12567 << subscription;
12568 break;
12573 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
12574 GLsizei length, const GLchar* marker) {
12575 if (!marker) {
12576 marker = "";
12578 debug_marker_manager_.SetMarker(
12579 length ? std::string(marker, length) : std::string(marker));
12582 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
12583 GLsizei length, const GLchar* marker) {
12584 if (!marker) {
12585 marker = "";
12587 std::string name = length ? std::string(marker, length) : std::string(marker);
12588 debug_marker_manager_.PushGroup(name);
12589 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name,
12590 kTraceGroupMarker);
12593 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
12594 debug_marker_manager_.PopGroup();
12595 gpu_tracer_->End(kTraceGroupMarker);
12598 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
12599 GLenum target, GLint image_id) {
12600 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
12602 if (target == GL_TEXTURE_CUBE_MAP) {
12603 LOCAL_SET_GL_ERROR(
12604 GL_INVALID_ENUM,
12605 "glBindTexImage2DCHROMIUM", "invalid target");
12606 return;
12609 // Default target might be conceptually valid, but disallow it to avoid
12610 // accidents.
12611 TextureRef* texture_ref =
12612 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12613 if (!texture_ref) {
12614 LOCAL_SET_GL_ERROR(
12615 GL_INVALID_OPERATION,
12616 "glBindTexImage2DCHROMIUM", "no texture bound");
12617 return;
12620 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
12621 if (!gl_image) {
12622 LOCAL_SET_GL_ERROR(
12623 GL_INVALID_OPERATION,
12624 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
12625 return;
12629 ScopedGLErrorSuppressor suppressor(
12630 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
12631 if (!gl_image->BindTexImage(target)) {
12632 LOCAL_SET_GL_ERROR(
12633 GL_INVALID_OPERATION,
12634 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
12635 return;
12639 gfx::Size size = gl_image->GetSize();
12640 texture_manager()->SetLevelInfo(
12641 texture_ref, target, 0, gl_image->GetInternalFormat(),
12642 size.width(), size.height(), 1, 0,
12643 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, true);
12644 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
12647 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
12648 GLenum target, GLint image_id) {
12649 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
12651 // Default target might be conceptually valid, but disallow it to avoid
12652 // accidents.
12653 TextureRef* texture_ref =
12654 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12655 if (!texture_ref) {
12656 LOCAL_SET_GL_ERROR(
12657 GL_INVALID_OPERATION,
12658 "glReleaseTexImage2DCHROMIUM", "no texture bound");
12659 return;
12662 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
12663 if (!gl_image) {
12664 LOCAL_SET_GL_ERROR(
12665 GL_INVALID_OPERATION,
12666 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
12667 return;
12670 // Do nothing when image is not currently bound.
12671 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
12672 return;
12675 ScopedGLErrorSuppressor suppressor(
12676 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
12677 gl_image->ReleaseTexImage(target);
12680 texture_manager()->SetLevelInfo(
12681 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
12682 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, false);
12685 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
12686 uint32 immediate_data_size,
12687 const void* cmd_data) {
12688 const gles2::cmds::TraceBeginCHROMIUM& c =
12689 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
12690 Bucket* category_bucket = GetBucket(c.category_bucket_id);
12691 Bucket* name_bucket = GetBucket(c.name_bucket_id);
12692 if (!category_bucket || category_bucket->size() == 0 ||
12693 !name_bucket || name_bucket->size() == 0) {
12694 return error::kInvalidArguments;
12697 std::string category_name;
12698 std::string trace_name;
12699 if (!category_bucket->GetAsString(&category_name) ||
12700 !name_bucket->GetAsString(&trace_name)) {
12701 return error::kInvalidArguments;
12704 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
12705 LOCAL_SET_GL_ERROR(
12706 GL_INVALID_OPERATION,
12707 "glTraceBeginCHROMIUM", "unable to create begin trace");
12708 return error::kNoError;
12710 return error::kNoError;
12713 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
12714 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
12715 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12716 "glTraceEndCHROMIUM", "no trace begin found");
12717 return;
12721 void GLES2DecoderImpl::DoDrawBuffersEXT(
12722 GLsizei count, const GLenum* bufs) {
12723 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
12724 LOCAL_SET_GL_ERROR(
12725 GL_INVALID_VALUE,
12726 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
12727 return;
12730 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
12731 if (framebuffer) {
12732 for (GLsizei i = 0; i < count; ++i) {
12733 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
12734 bufs[i] != GL_NONE) {
12735 LOCAL_SET_GL_ERROR(
12736 GL_INVALID_OPERATION,
12737 "glDrawBuffersEXT",
12738 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12739 return;
12742 glDrawBuffersARB(count, bufs);
12743 framebuffer->SetDrawBuffers(count, bufs);
12744 } else { // backbuffer
12745 if (count > 1 ||
12746 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
12747 LOCAL_SET_GL_ERROR(
12748 GL_INVALID_OPERATION,
12749 "glDrawBuffersEXT",
12750 "more than one buffer or bufs not GL_NONE or GL_BACK");
12751 return;
12753 GLenum mapped_buf = bufs[0];
12754 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12755 bufs[0] == GL_BACK) {
12756 mapped_buf = GL_COLOR_ATTACHMENT0;
12758 glDrawBuffersARB(count, &mapped_buf);
12759 group_->set_draw_buffer(bufs[0]);
12763 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
12764 MarkContextLost(GetContextLostReasonFromResetStatus(current));
12765 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
12766 reset_by_robustness_extension_ = true;
12769 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
12770 const GLfloat* matrix) {
12771 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12772 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12773 if (!features().chromium_path_rendering) {
12774 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12775 "glMatrixLoadfCHROMIUM",
12776 "function not available");
12777 return;
12780 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12781 ? state_.projection_matrix
12782 : state_.modelview_matrix;
12783 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
12784 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12785 // since the values of the _NV and _CHROMIUM tokens match.
12786 glMatrixLoadfEXT(matrix_mode, matrix);
12789 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
12790 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
12791 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
12793 if (!features().chromium_path_rendering) {
12794 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12795 "glMatrixLoadIdentityCHROMIUM",
12796 "function not available");
12797 return;
12800 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
12801 ? state_.projection_matrix
12802 : state_.modelview_matrix;
12803 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
12804 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12805 // since the values of the _NV and _CHROMIUM tokens match.
12806 glMatrixLoadIdentityEXT(matrix_mode);
12809 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12810 const char* function_name,
12811 TextureRef* texture_ref,
12812 GLenum target,
12813 GLint level,
12814 const void * data) {
12815 // We only support async uploads to 2D textures for now.
12816 if (GL_TEXTURE_2D != target) {
12817 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
12818 return false;
12820 // We only support uploads to level zero for now.
12821 if (level != 0) {
12822 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
12823 return false;
12825 // A transfer buffer must be bound, even for asyncTexImage2D.
12826 if (data == NULL) {
12827 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
12828 return false;
12830 // We only support one async transfer in progress.
12831 if (!texture_ref ||
12832 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
12833 LOCAL_SET_GL_ERROR(
12834 GL_INVALID_OPERATION,
12835 function_name, "transfer already in progress");
12836 return false;
12838 return true;
12841 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12842 uint32 async_upload_token,
12843 uint32 sync_data_shm_id,
12844 uint32 sync_data_shm_offset) {
12845 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
12846 if (!buffer.get() ||
12847 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
12848 return base::Closure();
12850 AsyncMemoryParams mem_params(buffer,
12851 sync_data_shm_offset,
12852 sizeof(AsyncUploadSync));
12854 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
12855 new AsyncUploadTokenCompletionObserver(async_upload_token));
12857 return base::Bind(
12858 &AsyncPixelTransferManager::AsyncNotifyCompletion,
12859 base::Unretained(GetAsyncPixelTransferManager()),
12860 mem_params,
12861 observer);
12864 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12865 uint32 immediate_data_size,
12866 const void* cmd_data) {
12867 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
12868 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
12869 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12870 GLenum target = static_cast<GLenum>(c.target);
12871 GLint level = static_cast<GLint>(c.level);
12872 GLenum internal_format = static_cast<GLenum>(c.internalformat);
12873 GLsizei width = static_cast<GLsizei>(c.width);
12874 GLsizei height = static_cast<GLsizei>(c.height);
12875 GLint border = static_cast<GLint>(c.border);
12876 GLenum format = static_cast<GLenum>(c.format);
12877 GLenum type = static_cast<GLenum>(c.type);
12878 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
12879 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
12880 uint32 pixels_size;
12881 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12882 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12883 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12885 base::ScopedClosureRunner scoped_completion_callback;
12886 if (async_upload_token) {
12887 base::Closure completion_closure =
12888 AsyncUploadTokenCompletionClosure(async_upload_token,
12889 sync_data_shm_id,
12890 sync_data_shm_offset);
12891 if (completion_closure.is_null())
12892 return error::kInvalidArguments;
12894 scoped_completion_callback.Reset(completion_closure);
12897 // TODO(epenner): Move this and copies of this memory validation
12898 // into ValidateTexImage2D step.
12899 if (!GLES2Util::ComputeImageDataSizes(
12900 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
12901 NULL, NULL)) {
12902 return error::kOutOfBounds;
12904 const void* pixels = NULL;
12905 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
12906 pixels = GetSharedMemoryAs<const void*>(
12907 pixels_shm_id, pixels_shm_offset, pixels_size);
12908 if (!pixels) {
12909 return error::kOutOfBounds;
12913 TextureManager::DoTexImageArguments args = {
12914 target, level, internal_format, width, height, 1, border, format, type,
12915 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
12916 TextureRef* texture_ref;
12917 // All the normal glTexSubImage2D validation.
12918 if (!texture_manager()->ValidateTexImage(
12919 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
12920 return error::kNoError;
12923 // Extra async validation.
12924 Texture* texture = texture_ref->texture();
12925 if (!ValidateAsyncTransfer(
12926 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
12927 return error::kNoError;
12929 // Don't allow async redefinition of a textures.
12930 if (texture->IsDefined()) {
12931 LOCAL_SET_GL_ERROR(
12932 GL_INVALID_OPERATION,
12933 "glAsyncTexImage2DCHROMIUM", "already defined");
12934 return error::kNoError;
12937 if (!EnsureGPUMemoryAvailable(pixels_size)) {
12938 LOCAL_SET_GL_ERROR(
12939 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
12940 return error::kNoError;
12943 // Setup the parameters.
12944 AsyncTexImage2DParams tex_params = {
12945 target, level, static_cast<GLenum>(internal_format),
12946 width, height, border, format, type};
12947 AsyncMemoryParams mem_params(
12948 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
12950 // Set up the async state if needed, and make the texture
12951 // immutable so the async state stays valid. The level info
12952 // is set up lazily when the transfer completes.
12953 AsyncPixelTransferDelegate* delegate =
12954 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
12955 tex_params);
12956 texture->SetImmutable(true);
12958 delegate->AsyncTexImage2D(
12959 tex_params,
12960 mem_params,
12961 base::Bind(&TextureManager::SetLevelInfoFromParams,
12962 // The callback is only invoked if the transfer delegate still
12963 // exists, which implies through manager->texture_ref->state
12964 // ownership that both of these pointers are valid.
12965 base::Unretained(texture_manager()),
12966 base::Unretained(texture_ref),
12967 tex_params));
12968 return error::kNoError;
12971 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12972 uint32 immediate_data_size,
12973 const void* cmd_data) {
12974 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
12975 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
12976 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12977 GLenum target = static_cast<GLenum>(c.target);
12978 GLint level = static_cast<GLint>(c.level);
12979 GLint xoffset = static_cast<GLint>(c.xoffset);
12980 GLint yoffset = static_cast<GLint>(c.yoffset);
12981 GLsizei width = static_cast<GLsizei>(c.width);
12982 GLsizei height = static_cast<GLsizei>(c.height);
12983 GLenum format = static_cast<GLenum>(c.format);
12984 GLenum type = static_cast<GLenum>(c.type);
12985 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
12986 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
12987 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
12989 base::ScopedClosureRunner scoped_completion_callback;
12990 if (async_upload_token) {
12991 base::Closure completion_closure =
12992 AsyncUploadTokenCompletionClosure(async_upload_token,
12993 sync_data_shm_id,
12994 sync_data_shm_offset);
12995 if (completion_closure.is_null())
12996 return error::kInvalidArguments;
12998 scoped_completion_callback.Reset(completion_closure);
13001 // TODO(epenner): Move this and copies of this memory validation
13002 // into ValidateTexSubImage2D step.
13003 uint32 data_size;
13004 if (!GLES2Util::ComputeImageDataSizes(
13005 width, height, 1, format, type, state_.unpack_alignment, &data_size,
13006 NULL, NULL)) {
13007 return error::kOutOfBounds;
13009 const void* pixels = GetSharedMemoryAs<const void*>(
13010 c.data_shm_id, c.data_shm_offset, data_size);
13012 // All the normal glTexSubImage2D validation.
13013 error::Error error = error::kNoError;
13014 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
13015 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
13016 return error;
13019 // Extra async validation.
13020 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13021 &state_, target);
13022 Texture* texture = texture_ref->texture();
13023 if (!ValidateAsyncTransfer(
13024 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
13025 return error::kNoError;
13027 // Guarantee async textures are always 'cleared' as follows:
13028 // - AsyncTexImage2D can not redefine an existing texture
13029 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13030 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13031 // - Textures become immutable after an async call.
13032 // This way we know in all cases that an async texture is always clear.
13033 if (!texture->SafeToRenderFrom()) {
13034 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
13035 target, level)) {
13036 LOCAL_SET_GL_ERROR(
13037 GL_OUT_OF_MEMORY,
13038 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13039 return error::kNoError;
13043 // Setup the parameters.
13044 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
13045 width, height, format, type};
13046 AsyncMemoryParams mem_params(
13047 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
13048 AsyncPixelTransferDelegate* delegate =
13049 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13050 if (!delegate) {
13051 // TODO(epenner): We may want to enforce exclusive use
13052 // of async APIs in which case this should become an error,
13053 // (the texture should have been async defined).
13054 AsyncTexImage2DParams define_params = {target, level,
13055 0, 0, 0, 0, 0, 0};
13056 texture->GetLevelSize(
13057 target, level, &define_params.width, &define_params.height, nullptr);
13058 texture->GetLevelType(
13059 target, level, &define_params.type, &define_params.internal_format);
13060 // Set up the async state if needed, and make the texture
13061 // immutable so the async state stays valid.
13062 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
13063 texture_ref, define_params);
13064 texture->SetImmutable(true);
13067 delegate->AsyncTexSubImage2D(tex_params, mem_params);
13068 return error::kNoError;
13071 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13072 uint32 immediate_data_size,
13073 const void* cmd_data) {
13074 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
13075 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
13076 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13077 GLenum target = static_cast<GLenum>(c.target);
13079 if (GL_TEXTURE_2D != target) {
13080 LOCAL_SET_GL_ERROR(
13081 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
13082 return error::kNoError;
13084 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13085 &state_, target);
13086 if (!texture_ref) {
13087 LOCAL_SET_GL_ERROR(
13088 GL_INVALID_OPERATION,
13089 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13090 return error::kNoError;
13092 AsyncPixelTransferDelegate* delegate =
13093 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
13094 if (!delegate) {
13095 LOCAL_SET_GL_ERROR(
13096 GL_INVALID_OPERATION,
13097 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13098 return error::kNoError;
13100 delegate->WaitForTransferCompletion();
13101 ProcessFinishedAsyncTransfers();
13102 return error::kNoError;
13105 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13106 uint32 immediate_data_size,
13107 const void* data) {
13108 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13110 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13111 ProcessFinishedAsyncTransfers();
13112 return error::kNoError;
13115 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
13116 uint32_t immediate_data_size, const void* cmd_data) {
13117 if (!unsafe_es3_apis_enabled())
13118 return error::kUnknownCommand;
13119 const gles2::cmds::UniformBlockBinding& c =
13120 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
13121 GLuint client_id = c.program;
13122 GLuint index = static_cast<GLuint>(c.index);
13123 GLuint binding = static_cast<GLuint>(c.binding);
13124 Program* program = GetProgramInfoNotShader(
13125 client_id, "glUniformBlockBinding");
13126 if (!program) {
13127 return error::kNoError;
13129 GLuint service_id = program->service_id();
13130 glUniformBlockBinding(service_id, index, binding);
13131 return error::kNoError;
13134 error::Error GLES2DecoderImpl::HandleClientWaitSync(
13135 uint32_t immediate_data_size, const void* cmd_data) {
13136 if (!unsafe_es3_apis_enabled())
13137 return error::kUnknownCommand;
13138 const gles2::cmds::ClientWaitSync& c =
13139 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
13140 GLuint sync = static_cast<GLuint>(c.sync);
13141 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13142 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13143 typedef cmds::ClientWaitSync::Result Result;
13144 Result* result_dst = GetSharedMemoryAs<Result*>(
13145 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
13146 if (!result_dst) {
13147 return error::kOutOfBounds;
13149 if (*result_dst != GL_WAIT_FAILED) {
13150 return error::kInvalidArguments;
13152 GLsync service_sync = 0;
13153 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13154 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
13155 return error::kNoError;
13157 *result_dst = glClientWaitSync(service_sync, flags, timeout);
13158 return error::kNoError;
13161 error::Error GLES2DecoderImpl::HandleWaitSync(
13162 uint32_t immediate_data_size, const void* cmd_data) {
13163 if (!unsafe_es3_apis_enabled())
13164 return error::kUnknownCommand;
13165 const gles2::cmds::WaitSync& c =
13166 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
13167 GLuint sync = static_cast<GLuint>(c.sync);
13168 GLbitfield flags = static_cast<GLbitfield>(c.flags);
13169 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
13170 GLsync service_sync = 0;
13171 if (!group_->GetSyncServiceId(sync, &service_sync)) {
13172 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
13173 return error::kNoError;
13175 glWaitSync(service_sync, flags, timeout);
13176 return error::kNoError;
13179 error::Error GLES2DecoderImpl::HandleMapBufferRange(
13180 uint32_t immediate_data_size, const void* cmd_data) {
13181 if (!unsafe_es3_apis_enabled()) {
13182 return error::kUnknownCommand;
13184 const gles2::cmds::MapBufferRange& c =
13185 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
13186 GLenum target = static_cast<GLenum>(c.target);
13187 GLbitfield access = static_cast<GLbitfield>(c.access);
13188 GLintptr offset = static_cast<GLintptr>(c.offset);
13189 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
13191 typedef cmds::MapBufferRange::Result Result;
13192 Result* result = GetSharedMemoryAs<Result*>(
13193 c.result_shm_id, c.result_shm_offset, sizeof(*result));
13194 if (!result) {
13195 return error::kOutOfBounds;
13197 if (*result != 0) {
13198 *result = 0;
13199 return error::kInvalidArguments;
13201 int8_t* mem =
13202 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
13203 if (!mem) {
13204 return error::kOutOfBounds;
13207 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
13208 if ((access & mask) == mask) {
13209 // TODO(zmo): To be on the safe side, always map
13210 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13211 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
13212 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
13214 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13215 // undefined behaviors.
13216 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
13217 if ((access & mask) == mask) {
13218 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
13219 "incompatible access bits");
13220 return error::kNoError;
13222 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
13223 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
13224 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13225 access = (access | GL_MAP_READ_BIT);
13227 void* ptr = glMapBufferRange(target, offset, size, access);
13228 if (ptr == nullptr) {
13229 return error::kNoError;
13231 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13232 DCHECK(buffer);
13233 buffer->SetMappedRange(offset, size, access, ptr,
13234 GetSharedMemoryBuffer(c.data_shm_id));
13235 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
13236 memcpy(mem, ptr, size);
13238 *result = 1;
13239 return error::kNoError;
13242 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
13243 uint32_t immediate_data_size, const void* cmd_data) {
13244 if (!unsafe_es3_apis_enabled()) {
13245 return error::kUnknownCommand;
13247 const gles2::cmds::UnmapBuffer& c =
13248 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
13249 GLenum target = static_cast<GLenum>(c.target);
13251 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
13252 if (!buffer) {
13253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
13254 return error::kNoError;
13256 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
13257 if (!mapped_range) {
13258 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
13259 "buffer is unmapped");
13260 return error::kNoError;
13262 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
13263 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
13264 GL_MAP_FLUSH_EXPLICIT_BIT) {
13265 // If we don't need to write back, or explict flush is required, no copying
13266 // back is needed.
13267 } else {
13268 void* mem = mapped_range->GetShmPointer();
13269 if (!mem) {
13270 return error::kOutOfBounds;
13272 DCHECK(mapped_range->pointer);
13273 memcpy(mapped_range->pointer, mem, mapped_range->size);
13275 buffer->RemoveMappedRange();
13276 GLboolean rt = glUnmapBuffer(target);
13277 if (rt == GL_FALSE) {
13278 // At this point, we have already done the necessary validation, so
13279 // GL_FALSE indicates data corruption.
13280 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13281 // the second unmap could still return GL_FALSE. For now, we simply lose
13282 // the contexts in the share group.
13283 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13284 // Need to lose current context before broadcasting!
13285 MarkContextLost(error::kGuilty);
13286 group_->LoseContexts(error::kInnocent);
13287 return error::kLostContext;
13289 return error::kNoError;
13292 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13293 TextureRef* texture_ref) {
13294 Texture* texture = texture_ref->texture();
13295 DoDidUseTexImageIfNeeded(texture, texture->target());
13298 // Note that GL_LOST_CONTEXT is specific to GLES.
13299 // For desktop GL we have to query the reset status proactively.
13300 void GLES2DecoderImpl::OnContextLostError() {
13301 if (!WasContextLost()) {
13302 // Need to lose current context before broadcasting!
13303 CheckResetStatus();
13304 group_->LoseContexts(error::kUnknown);
13305 reset_by_robustness_extension_ = true;
13309 void GLES2DecoderImpl::OnOutOfMemoryError() {
13310 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
13311 error::ContextLostReason other = error::kOutOfMemory;
13312 if (CheckResetStatus()) {
13313 other = error::kUnknown;
13314 } else {
13315 // Need to lose current context before broadcasting!
13316 MarkContextLost(error::kOutOfMemory);
13318 group_->LoseContexts(other);
13322 // Include the auto-generated part of this file. We split this because it means
13323 // we can easily edit the non-auto generated parts right here in this file
13324 // instead of having to edit some template or the code generator.
13325 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
13327 } // namespace gles2
13328 } // namespace gpu