Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: gpu/command_buffer/service/gles2_cmd_decoder.cc

Issue 1426903002: gpu: Make glTexSubImage2D work with GL_SRGB_ALPHA on OpenGL (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
6 6
7 #include <stdio.h> 7 #include <stdio.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 } 183 }
184 184
185 struct Vec4f { 185 struct Vec4f {
186 explicit Vec4f(const Vec4& data) { 186 explicit Vec4f(const Vec4& data) {
187 data.GetValues(v); 187 data.GetValues(v);
188 } 188 }
189 189
190 GLfloat v[4]; 190 GLfloat v[4];
191 }; 191 };
192 192
193 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
194 // contains the other rectangle or shares an edge with the other rectangle.
195 bool CombineAdjacentRects(const gfx::Rect& rect1,
196 const gfx::Rect& rect2,
197 gfx::Rect* result) {
198 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
199 if (rect1.IsEmpty() || rect2.Contains(rect1)) {
200 *result = rect2;
201 return true;
202 }
203
204 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
205 if (rect2.IsEmpty() || rect1.Contains(rect2)) {
206 *result = rect1;
207 return true;
208 }
209
210 // Return the union of |rect1| and |rect2| if they share an edge.
211 if (rect1.SharesEdgeWith(rect2)) {
212 *result = gfx::UnionRects(rect1, rect2);
213 return true;
214 }
215
216 // Return false if it's not possible to combine |rect1| and |rect2|.
217 return false;
218 }
219
220 GLenum ExtractFormatFromStorageFormat(GLenum internalformat) { 193 GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
221 switch (internalformat) { 194 switch (internalformat) {
222 case GL_R8: 195 case GL_R8:
223 case GL_R8_SNORM: 196 case GL_R8_SNORM:
224 case GL_R16F: 197 case GL_R16F:
225 case GL_R32F: 198 case GL_R32F:
226 return GL_RED; 199 return GL_RED;
227 case GL_R8UI: 200 case GL_R8UI:
228 case GL_R8I: 201 case GL_R8I:
229 case GL_R16UI: 202 case GL_R16UI:
(...skipping 10864 matching lines...) Expand 10 before | Expand all | Expand 10 after
11094 GLint copyX = 0; 11067 GLint copyX = 0;
11095 GLint copyY = 0; 11068 GLint copyY = 0;
11096 GLint copyWidth = 0; 11069 GLint copyWidth = 0;
11097 GLint copyHeight = 0; 11070 GLint copyHeight = 0;
11098 Clip(x, width, size.width(), &copyX, &copyWidth); 11071 Clip(x, width, size.width(), &copyX, &copyWidth);
11099 Clip(y, height, size.height(), &copyY, &copyHeight); 11072 Clip(y, height, size.height(), &copyY, &copyHeight);
11100 11073
11101 if (xoffset != 0 || yoffset != 0 || width != size.width() || 11074 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
11102 height != size.height()) { 11075 height != size.height()) {
11103 gfx::Rect cleared_rect; 11076 gfx::Rect cleared_rect;
11104 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), 11077 if (TextureManager::CombineAdjacentRects(
11105 gfx::Rect(xoffset, yoffset, width, height), 11078 texture->GetLevelClearedRect(target, level),
11106 &cleared_rect)) { 11079 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) {
11107 DCHECK_GE(cleared_rect.size().GetArea(), 11080 DCHECK_GE(cleared_rect.size().GetArea(),
11108 texture->GetLevelClearedRect(target, level).size().GetArea()); 11081 texture->GetLevelClearedRect(target, level).size().GetArea());
11109 texture_manager()->SetLevelClearedRect(texture_ref, target, level, 11082 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
11110 cleared_rect); 11083 cleared_rect);
11111 } else { 11084 } else {
11112 // Otherwise clear part of texture level that is not already cleared. 11085 // Otherwise clear part of texture level that is not already cleared.
11113 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 11086 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
11114 level)) { 11087 level)) {
11115 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", 11088 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
11116 "dimensions too big"); 11089 "dimensions too big");
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
11150 glCopyTexSubImage2D(target, level, 11123 glCopyTexSubImage2D(target, level,
11151 destX, destY, copyX, copyY, 11124 destX, destY, copyX, copyY,
11152 copyWidth, copyHeight); 11125 copyWidth, copyHeight);
11153 } 11126 }
11154 11127
11155 // This may be a slow command. Exit command processing to allow for 11128 // This may be a slow command. Exit command processing to allow for
11156 // context preemption and GPU watchdog checks. 11129 // context preemption and GPU watchdog checks.
11157 ExitCommandProcessingEarly(); 11130 ExitCommandProcessingEarly();
11158 } 11131 }
11159 11132
11160 bool GLES2DecoderImpl::ValidateTexSubImage2D(
11161 error::Error* error,
11162 const char* function_name,
11163 GLenum target,
11164 GLint level,
11165 GLint xoffset,
11166 GLint yoffset,
11167 GLsizei width,
11168 GLsizei height,
11169 GLenum format,
11170 GLenum type,
11171 const void * data) {
11172 (*error) = error::kNoError;
11173 if (!validators_->texture_target.IsValid(target)) {
11174 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
11175 return false;
11176 }
11177 // TODO(ccameron): Add a separate texture from |texture_target| for
11178 // [Compressed]Tex[Sub]Image2D and related functions.
11179 // http://crbug.com/536854
11180 if (target == GL_TEXTURE_RECTANGLE_ARB) {
11181 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
11182 return false;
11183 }
11184 if (width < 0) {
11185 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
11186 return false;
11187 }
11188 if (height < 0) {
11189 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
11190 return false;
11191 }
11192 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11193 &state_, target);
11194 if (!texture_ref) {
11195 LOCAL_SET_GL_ERROR(
11196 GL_INVALID_OPERATION,
11197 function_name, "unknown texture for target");
11198 return false;
11199 }
11200 Texture* texture = texture_ref->texture();
11201 GLenum current_type = 0;
11202 GLenum internal_format = 0;
11203 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
11204 LOCAL_SET_GL_ERROR(
11205 GL_INVALID_OPERATION, function_name, "level does not exist.");
11206 return false;
11207 }
11208 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
11209 function_name, format, type, internal_format, level)) {
11210 return false;
11211 }
11212 if (type != current_type && !feature_info_->IsES3Enabled()) {
11213 LOCAL_SET_GL_ERROR(
11214 GL_INVALID_OPERATION,
11215 function_name, "type does not match type of texture.");
11216 return false;
11217 }
11218 if (!texture->ValidForTexture(
11219 target, level, xoffset, yoffset, 0, width, height, 1)) {
11220 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
11221 return false;
11222 }
11223 if ((GLES2Util::GetChannelsForFormat(format) &
11224 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0
11225 && !feature_info_->IsES3Enabled()) {
11226 LOCAL_SET_GL_ERROR(
11227 GL_INVALID_OPERATION,
11228 function_name, "can not supply data for depth or stencil textures");
11229 return false;
11230 }
11231 if (data == NULL) {
11232 (*error) = error::kOutOfBounds;
11233 return false;
11234 }
11235 return true;
11236 }
11237
11238 error::Error GLES2DecoderImpl::DoTexSubImage2D(
11239 GLenum target,
11240 GLint level,
11241 GLint xoffset,
11242 GLint yoffset,
11243 GLsizei width,
11244 GLsizei height,
11245 GLenum format,
11246 GLenum type,
11247 const void * data) {
11248 error::Error error = error::kNoError;
11249 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
11250 xoffset, yoffset, width, height, format, type, data)) {
11251 return error;
11252 }
11253 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11254 &state_, target);
11255 Texture* texture = texture_ref->texture();
11256 GLsizei tex_width = 0;
11257 GLsizei tex_height = 0;
11258 bool ok = texture->GetLevelSize(
11259 target, level, &tex_width, &tex_height, nullptr);
11260 DCHECK(ok);
11261 if (xoffset != 0 || yoffset != 0 ||
11262 width != tex_width || height != tex_height) {
11263 gfx::Rect cleared_rect;
11264 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
11265 gfx::Rect(xoffset, yoffset, width, height),
11266 &cleared_rect)) {
11267 DCHECK_GE(cleared_rect.size().GetArea(),
11268 texture->GetLevelClearedRect(target, level).size().GetArea());
11269 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
11270 cleared_rect);
11271 } else {
11272 // Otherwise clear part of texture level that is not already cleared.
11273 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
11274 level)) {
11275 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
11276 "dimensions too big");
11277 return error::kNoError;
11278 }
11279 }
11280 ScopedTextureUploadTimer timer(&texture_state_);
11281 glTexSubImage2D(
11282 target, level, xoffset, yoffset, width, height, format, type, data);
11283 return error::kNoError;
11284 }
11285
11286 if (!texture_state_.texsubimage_faster_than_teximage &&
11287 !texture->IsImmutable() &&
11288 !texture->HasImages()) {
11289 ScopedTextureUploadTimer timer(&texture_state_);
11290 GLenum internal_format;
11291 GLenum tex_type;
11292 texture->GetLevelType(target, level, &tex_type, &internal_format);
11293 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
11294 // to look it up.
11295 glTexImage2D(
11296 target, level, internal_format, width, height, 0, format, type, data);
11297 } else {
11298 ScopedTextureUploadTimer timer(&texture_state_);
11299 glTexSubImage2D(
11300 target, level, xoffset, yoffset, width, height, format, type, data);
11301 }
11302 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
11303
11304 // This may be a slow command. Exit command processing to allow for
11305 // context preemption and GPU watchdog checks.
11306 ExitCommandProcessingEarly();
11307 return error::kNoError;
11308 }
11309
11310 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, 11133 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
11311 const void* cmd_data) { 11134 const void* cmd_data) {
11312 const gles2::cmds::TexSubImage2D& c = 11135 const gles2::cmds::TexSubImage2D& c =
11313 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data); 11136 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
11314 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", 11137 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
11315 "width", c.width, "height", c.height); 11138 "width", c.width, "height", c.height);
11316 GLboolean internal = static_cast<GLboolean>(c.internal); 11139 GLboolean internal = static_cast<GLboolean>(c.internal);
11317 if (internal == GL_TRUE && texture_state_.tex_image_failed) 11140 if (internal == GL_TRUE && texture_state_.tex_image_failed)
11318 return error::kNoError; 11141 return error::kNoError;
11319 11142
11320 GLenum target = static_cast<GLenum>(c.target); 11143 GLenum target = static_cast<GLenum>(c.target);
11321 GLint level = static_cast<GLint>(c.level); 11144 GLint level = static_cast<GLint>(c.level);
11322 GLint xoffset = static_cast<GLint>(c.xoffset); 11145 GLint xoffset = static_cast<GLint>(c.xoffset);
11323 GLint yoffset = static_cast<GLint>(c.yoffset); 11146 GLint yoffset = static_cast<GLint>(c.yoffset);
11324 GLsizei width = static_cast<GLsizei>(c.width); 11147 GLsizei width = static_cast<GLsizei>(c.width);
11325 GLsizei height = static_cast<GLsizei>(c.height); 11148 GLsizei height = static_cast<GLsizei>(c.height);
11326 GLenum format = static_cast<GLenum>(c.format); 11149 GLenum format = static_cast<GLenum>(c.format);
11327 GLenum type = static_cast<GLenum>(c.type); 11150 GLenum type = static_cast<GLenum>(c.type);
11328 uint32 data_size; 11151 uint32 data_size;
11329 if (!GLES2Util::ComputeImageDataSizes( 11152 if (!GLES2Util::ComputeImageDataSizes(
11330 width, height, 1, format, type, state_.unpack_alignment, &data_size, 11153 width, height, 1, format, type, state_.unpack_alignment, &data_size,
11331 NULL, NULL)) { 11154 NULL, NULL)) {
11332 return error::kOutOfBounds; 11155 return error::kOutOfBounds;
11333 } 11156 }
11157
11334 const void* pixels = GetSharedMemoryAs<const void*>( 11158 const void* pixels = GetSharedMemoryAs<const void*>(
11335 c.pixels_shm_id, c.pixels_shm_offset, data_size); 11159 c.pixels_shm_id, c.pixels_shm_offset, data_size);
11336 return DoTexSubImage2D( 11160 if (!pixels)
11337 target, level, xoffset, yoffset, width, height, format, type, pixels); 11161 return error::kOutOfBounds;
bajones 2015/10/28 20:23:26 Seems like kInvalidArguments might be a better err
Kimmo Kinnunen 2015/10/29 06:21:17 The intention was not to change behavior wrt this.
11162
11163 TextureManager::DoTexSubImageArguments args = {
11164 target, level, xoffset, yoffset, width,
11165 height, format, type, pixels, data_size};
11166 texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_,
11167 &framebuffer_state_,
11168 "glTexSubImage2D", args);
11169
11170 // This may be a slow command. Exit command processing to allow for
11171 // context preemption and GPU watchdog checks.
11172 ExitCommandProcessingEarly();
11173 return error::kNoError;
11338 } 11174 }
11339 11175
11340 error::Error GLES2DecoderImpl::DoTexSubImage3D( 11176 error::Error GLES2DecoderImpl::DoTexSubImage3D(
11341 GLenum target, 11177 GLenum target,
11342 GLint level, 11178 GLint level,
11343 GLint xoffset, 11179 GLint xoffset,
11344 GLint yoffset, 11180 GLint yoffset,
11345 GLint zoffset, 11181 GLint zoffset,
11346 GLsizei width, 11182 GLsizei width,
11347 GLsizei height, 11183 GLsizei height,
(...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after
13265 } 13101 }
13266 13102
13267 int dest_width = 0; 13103 int dest_width = 0;
13268 int dest_height = 0; 13104 int dest_height = 0;
13269 bool ok = dest_texture->GetLevelSize( 13105 bool ok = dest_texture->GetLevelSize(
13270 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); 13106 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
13271 DCHECK(ok); 13107 DCHECK(ok);
13272 if (xoffset != 0 || yoffset != 0 || width != dest_width || 13108 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
13273 height != dest_height) { 13109 height != dest_height) {
13274 gfx::Rect cleared_rect; 13110 gfx::Rect cleared_rect;
13275 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), 13111 if (TextureManager::CombineAdjacentRects(
13276 gfx::Rect(xoffset, yoffset, width, height), 13112 dest_texture->GetLevelClearedRect(target, 0),
13277 &cleared_rect)) { 13113 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) {
13278 DCHECK_GE(cleared_rect.size().GetArea(), 13114 DCHECK_GE(cleared_rect.size().GetArea(),
13279 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); 13115 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
13280 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, 13116 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
13281 cleared_rect); 13117 cleared_rect);
13282 } else { 13118 } else {
13283 // Otherwise clear part of texture level that is not already cleared. 13119 // Otherwise clear part of texture level that is not already cleared.
13284 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, 13120 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
13285 0)) { 13121 0)) {
13286 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", 13122 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
13287 "destination texture dimensions too big"); 13123 "destination texture dimensions too big");
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
13603 } 13439 }
13604 13440
13605 int dest_width = 0; 13441 int dest_width = 0;
13606 int dest_height = 0; 13442 int dest_height = 0;
13607 bool ok = dest_texture->GetLevelSize( 13443 bool ok = dest_texture->GetLevelSize(
13608 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); 13444 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
13609 DCHECK(ok); 13445 DCHECK(ok);
13610 if (xoffset != 0 || yoffset != 0 || width != dest_width || 13446 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
13611 height != dest_height) { 13447 height != dest_height) {
13612 gfx::Rect cleared_rect; 13448 gfx::Rect cleared_rect;
13613 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), 13449 if (TextureManager::CombineAdjacentRects(
13614 gfx::Rect(xoffset, yoffset, width, height), 13450 dest_texture->GetLevelClearedRect(target, 0),
13615 &cleared_rect)) { 13451 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) {
13616 DCHECK_GE(cleared_rect.size().GetArea(), 13452 DCHECK_GE(cleared_rect.size().GetArea(),
13617 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); 13453 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
13618 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, 13454 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
13619 cleared_rect); 13455 cleared_rect);
13620 } else { 13456 } else {
13621 // Otherwise clear part of texture level that is not already cleared. 13457 // Otherwise clear part of texture level that is not already cleared.
13622 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, 13458 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
13623 0)) { 13459 0)) {
13624 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, 13460 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY,
13625 "glCompressedCopySubTextureCHROMIUM", 13461 "glCompressedCopySubTextureCHROMIUM",
(...skipping 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after
14980 return error::kNoError; 14816 return error::kNoError;
14981 } 14817 }
14982 14818
14983 // Include the auto-generated part of this file. We split this because it means 14819 // Include the auto-generated part of this file. We split this because it means
14984 // we can easily edit the non-auto generated parts right here in this file 14820 // we can easily edit the non-auto generated parts right here in this file
14985 // instead of having to edit some template or the code generator. 14821 // instead of having to edit some template or the code generator.
14986 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" 14822 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14987 14823
14988 } // namespace gles2 14824 } // namespace gles2
14989 } // namespace gpu 14825 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698