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

Unified Diff: gpu/command_buffer/service/gles2_cmd_decoder.cc

Issue 793693003: Tile Compression (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/service/feature_info.cc ('k') | gpu/command_buffer/service/gles2_cmd_decoder_autogen.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/command_buffer/service/gles2_cmd_decoder.cc
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index f97710e86a61009ce7b6b54517f63040d5f8cb3b..7257dfa17d1d6f20ed0468db7f79a665b378fdd6 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -167,6 +167,25 @@ static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
}
}
+static size_t BitsPerPixel(GLenum format) {
+ switch (format) {
+ case GL_RGB:
+ return 24;
+ case GL_RGBA:
+ return 32;
+ case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return 8;
+ case GL_ATC_RGB_AMD:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_ETC1_RGB8_OES:
+ return 4;
+ }
+
+ NOTREACHED();
+ return 0;
+}
+
} // namespace
class GLES2DecoderImpl;
@@ -944,6 +963,12 @@ class GLES2DecoderImpl : public GLES2Decoder,
GLenum internal_format,
GLenum dest_type);
+ void DoCopyCompressedTextureCHROMIUM(GLenum target,
+ GLuint source_id,
+ GLuint target_id,
+ GLenum internal_format,
+ GLenum dest_type);
+
// Wrapper for TexStorage2DEXT.
void DoTexStorage2DEXT(
GLenum target,
@@ -1652,6 +1677,18 @@ class GLES2DecoderImpl : public GLES2Decoder,
GLsizei width, GLsizei height, GLenum format,
Texture* texture);
+ bool ValidateCompressedTexSubImage2D(error::Error* error,
+ const char* function_name,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei image_size,
+ const void* data);
+
void RenderWarning(const char* filename, int line, const std::string& msg);
void PerformanceWarning(
const char* filename, int line, const std::string& msg);
@@ -2839,8 +2876,12 @@ Capabilities GLES2DecoderImpl::GetCapabilities() {
caps.egl_image_external =
feature_info_->feature_flags().oes_egl_image_external;
+ caps.texture_format_atc =
+ feature_info_->feature_flags().ext_texture_format_atc;
caps.texture_format_bgra8888 =
feature_info_->feature_flags().ext_texture_format_bgra8888;
+ caps.texture_format_dxt =
+ feature_info_->feature_flags().ext_texture_format_dxt;
caps.texture_format_etc1 =
feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
caps.texture_format_etc1_npot =
@@ -8343,70 +8384,18 @@ bool GLES2DecoderImpl::ClearLevel(
return true;
}
-namespace {
-
-const int kS3TCBlockWidth = 4;
-const int kS3TCBlockHeight = 4;
-const int kS3TCDXT1BlockSize = 8;
-const int kS3TCDXT3AndDXT5BlockSize = 16;
-
-bool IsValidDXTSize(GLint level, GLsizei size) {
- return (size == 1) ||
- (size == 2) || !(size % kS3TCBlockWidth);
-}
-
-bool IsValidPVRTCSize(GLint level, GLsizei size) {
- return GLES2Util::IsPOT(size);
-}
-
-} // anonymous namespace.
-
bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
const char* function_name,
GLsizei width, GLsizei height, GLenum format, size_t size) {
- unsigned int bytes_required = 0;
+ int bytes_required = 0;
- switch (format) {
- case GL_ATC_RGB_AMD:
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_ETC1_RGB8_OES: {
- int num_blocks_across =
- (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
- int num_blocks_down =
- (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
- int num_blocks = num_blocks_across * num_blocks_down;
- bytes_required = num_blocks * kS3TCDXT1BlockSize;
- break;
- }
- case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
- case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
- int num_blocks_across =
- (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
- int num_blocks_down =
- (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
- int num_blocks = num_blocks_across * num_blocks_down;
- bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
- break;
- }
- case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
- case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
- bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
- break;
- }
- case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
- case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
- bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
- break;
- }
- default:
- LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
- return false;
+ if (!GLES2Util::ComputeCompressedImageSize(width, height, format,
+ &bytes_required)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
+ return false;
}
- if (size != bytes_required) {
+ if (size != static_cast<size_t>(bytes_required)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
return false;
@@ -8418,47 +8407,13 @@ bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
const char* function_name,
GLint level, GLsizei width, GLsizei height, GLenum format) {
- switch (format) {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
- if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name,
- "width or height invalid for level");
- return false;
- }
- return true;
- }
- case GL_ATC_RGB_AMD:
- case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
- case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
- case GL_ETC1_RGB8_OES: {
- if (width <= 0 || height <= 0) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name,
- "width or height invalid for level");
- return false;
- }
- return true;
- }
- case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
- case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
- case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
- case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
- if (!IsValidPVRTCSize(level, width) ||
- !IsValidPVRTCSize(level, height)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name,
- "width or height invalid for level");
- return false;
- }
- return true;
- }
- default:
- return false;
+ if (!GLES2Util::IsValidCompressedImageSize(level, width, height, format)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+ "width or height invalid for level");
+ return false;
}
+
+ return true;
}
bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
@@ -8473,10 +8428,13 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
}
switch (format) {
+ case GL_ATC_RGB_AMD:
+ case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_ETC1_RGB8_OES: {
const int kBlockWidth = 4;
const int kBlockHeight = 4;
if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
@@ -8497,20 +8455,12 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
return ValidateCompressedTexDimensions(
function_name, level, width, height, format);
}
- case GL_ATC_RGB_AMD:
- case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
- case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
+ case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD: {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name,
"not supported for ATC textures");
return false;
}
- case GL_ETC1_RGB8_OES: {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name,
- "not supported for ECT1_RGB8_OES textures");
- return false;
- }
case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
@@ -8539,6 +8489,72 @@ bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
}
}
+bool GLES2DecoderImpl::ValidateCompressedTexSubImage2D(
+ error::Error* error,
+ const char* function_name,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei image_size,
+ const void* data) {
+ (*error) = error::kNoError;
+ if (!validators_->texture_target.IsValid(target)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
+ return false;
+ }
+ if (width < 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
+ return false;
+ }
+ if (height < 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
+ return false;
+ }
+ TextureRef* texture_ref =
+ texture_manager()->GetTextureInfoForTarget(&state_, target);
+ if (!texture_ref) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+ "unknown texture for target");
+ return false;
+ }
+ Texture* texture = texture_ref->texture();
+ GLenum current_type = 0;
+ GLenum internal_format = 0;
+ if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+ "level does not exist.");
+ return false;
+ }
+ if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+ "async upload pending for texture");
+ return false;
+ }
+ if (!ValidateCompressedTexFuncData(function_name, width, height, format,
+ image_size)) {
+ return false;
+ }
+ if (!ValidateCompressedTexSubDimensions(function_name, target, level, xoffset,
+ yoffset, width, height, format,
+ texture)) {
+ return false;
+ }
+ if (!texture->ValidForTexture(target, level, xoffset, yoffset, width, height,
+ GL_UNSIGNED_BYTE)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
+ return false;
+ }
+ if (data == NULL) {
+ (*error) = error::kOutOfBounds;
+ return false;
+ }
+ return true;
+}
+
error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
GLenum target,
GLint level,
@@ -10587,6 +10603,149 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
}
+void GLES2DecoderImpl::DoCopyCompressedTextureCHROMIUM(GLenum target,
+ GLuint source_id,
+ GLuint dest_id,
+ GLenum internal_format,
+ GLenum dest_type) {
+ TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyCompressedTextureCHROMIUM");
+
+ TextureRef* dest_texture_ref = GetTexture(dest_id);
+ TextureRef* source_texture_ref = GetTexture(source_id);
+
+ if (!source_texture_ref || !dest_texture_ref) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
+ "unknown texture id");
+ return;
+ }
+
+ if (GL_TEXTURE_2D != target) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
+ "invalid texture target");
+ return;
+ }
+
+ Texture* source_texture = source_texture_ref->texture();
+ Texture* dest_texture = dest_texture_ref->texture();
+ if (dest_texture->target() != GL_TEXTURE_2D ||
+ (source_texture->target() != GL_TEXTURE_2D &&
+ source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
+ source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
+ "invalid texture target binding");
+ return;
+ }
+
+ gfx::GLImage* image =
+ source_texture->GetLevelImage(source_texture->target(), 0);
+ if (!image) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
+ "source texture has no level 0");
+ return;
+ }
+
+ gfx::Size size = image->GetSize();
+ int source_width = size.width();
+ int source_height = size.height();
+ if (source_width <= 0 || source_height <= 0) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyCompressedTextureCHROMIUM",
+ "invalid image size");
+ return;
+ }
+
+ // Clear the source texture if necessary.
+ if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
+ source_texture->target(), 0)) {
+ LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyCompressedTextureCHROMIUM",
+ "dimensions too big");
+ return;
+ }
+
+ GLenum source_type = 0;
+ GLenum source_internal_format = 0;
+ source_texture->GetLevelType(source_texture->target(), 0, &source_type,
+ &source_internal_format);
+
+ // The destination format should be one of the supported compressed formats.
+ bool valid_dest_format =
+ internal_format == GL_ATC_RGB_AMD ||
+ internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
+ internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
+ internal_format == GL_ETC1_RGB8_OES;
+ bool valid_source_format = source_internal_format == GL_ALPHA ||
+ source_internal_format == GL_RGB ||
+ source_internal_format == GL_RGBA ||
+ source_internal_format == GL_LUMINANCE ||
+ source_internal_format == GL_LUMINANCE_ALPHA ||
+ source_internal_format == GL_BGRA_EXT;
+ if (!valid_source_format || !valid_dest_format) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyCompressedTextureCHROMIUM",
+ "invalid internal format");
+ return;
+ }
+
+ // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
+ // needed because it takes 10s of milliseconds to initialize.
+ if (!copy_texture_CHROMIUM_.get()) {
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyCompressedTextureCHROMIUM");
+ copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
+ copy_texture_CHROMIUM_->Initialize(this);
+ RestoreCurrentFramebufferBindings();
+ if (LOCAL_PEEK_GL_ERROR("glCopyCompressedTextureCHROMIUM") != GL_NO_ERROR)
+ return;
+ }
+
+ GLenum dest_type_previous = dest_type;
+ GLenum dest_internal_format = internal_format;
+ int dest_width = 0, dest_height = 0;
+ bool dest_level_defined =
+ dest_texture->GetLevelSize(GL_TEXTURE_2D, 0, &dest_width, &dest_height);
+
+ if (dest_level_defined) {
+ dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
+ &dest_internal_format);
+ }
+
+ // Resize the destination texture to the dimensions of the source texture.
+ if (!dest_level_defined || dest_width != source_width ||
+ dest_height != source_height || dest_internal_format != internal_format ||
+ dest_type_previous != dest_type) {
+ // Compute image byte size.
+ GLsizei image_size =
+ source_width * source_height * BitsPerPixel(internal_format) / 8;
+
+ // Ensure that the glCompressedTexImage2D succeeds.
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyCompressedTextureCHROMIUM");
+ glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width,
+ source_height, 0, image_size, NULL);
+
+ GLenum error = LOCAL_PEEK_GL_ERROR("glCopyCompressedTextureCHROMIUM");
+ if (error != GL_NO_ERROR) {
+ RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
+ return;
+ }
+
+ texture_manager()->SetLevelInfo(
+ dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
+ source_height, 1, 0, internal_format, dest_type, true);
+ } else {
+ texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
+ true);
+ }
+
+ ScopedModifyPixels modify(dest_texture_ref);
+
+ DCHECK(!unpack_flip_y_);
+ DCHECK(!(unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_));
+
+ // Copying compressed textures is only supported using GLImage::CopyTexImage.
+ glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
+ bool copy_result = image->CopyTexImage(GL_TEXTURE_2D);
+ DCHECK(copy_result);
+}
+
static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
switch (internalformat) {
case GL_RGB565:
@@ -11472,6 +11631,214 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleAsyncCompressedTexImage2DCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ const gles2::cmds::AsyncCompressedTexImage2DCHROMIUM& c =
+ *static_cast<const gles2::cmds::AsyncCompressedTexImage2DCHROMIUM*>(
+ cmd_data);
+ GLenum target = static_cast<GLenum>(c.target);
+ GLint level = static_cast<GLint>(c.level);
+ // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
+ // unsigned integer for internalformat.
+ GLenum internal_format = static_cast<GLenum>(c.internalformat);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLint border = static_cast<GLint>(c.border);
+ GLsizei image_size = static_cast<GLenum>(c.imagesize);
+ uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
+ uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
+ uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
+ uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
+ uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
+
+ base::ScopedClosureRunner scoped_completion_callback;
+ if (async_upload_token) {
+ base::Closure completion_closure = AsyncUploadTokenCompletionClosure(
+ async_upload_token, sync_data_shm_id, sync_data_shm_offset);
+ if (completion_closure.is_null())
+ return error::kInvalidArguments;
+
+ scoped_completion_callback.Reset(completion_closure);
+ }
+
+ const void* pixels = NULL;
+ if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
+ pixels = GetSharedMemoryAs<const void*>(pixels_shm_id, pixels_shm_offset,
+ image_size);
+ if (!pixels) {
+ return error::kOutOfBounds;
+ }
+ }
+
+ TextureManager::DoCompressedTexImage2DArguments args = {target,
+ level,
+ internal_format,
+ width,
+ height,
+ border,
+ image_size,
+ pixels};
+ TextureRef* texture_ref;
+ // All the normal glCompressedTexImage2D validation.
+ if (!texture_manager()->ValidateCompressedTexImage2D(
+ &state_, "glAsyncCompressedTexImage2DCHROMIUM", args, &texture_ref)) {
+ return error::kNoError;
+ }
+
+ // Extra async validation.
+ Texture* texture = texture_ref->texture();
+ if (!ValidateAsyncTransfer("glAsyncCompressedTexImage2DCHROMIUM", texture_ref,
+ target, level, pixels))
+ return error::kNoError;
+
+ // Don't allow async redefinition of a textures.
+ if (texture->IsDefined()) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glAsyncCompressedTexImage2DCHROMIUM",
+ "already defined");
+ return error::kNoError;
+ }
+
+ if (!EnsureGPUMemoryAvailable(image_size)) {
+ LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glAsyncCompressedTexImage2DCHROMIUM",
+ "out of memory");
+ return error::kNoError;
+ }
+
+ // Setup the parameters.
+ AsyncCompressedTexImage2DParams tex_params = {
+ target,
+ level,
+ static_cast<GLenum>(internal_format),
+ width,
+ height,
+ border,
+ image_size};
+ AsyncMemoryParams mem_params(GetSharedMemoryBuffer(c.pixels_shm_id),
+ c.pixels_shm_offset, image_size);
+
+ // Set up the async state if needed, and make the texture
+ // immutable so the async state stays valid. The level info
+ // is set up lazily when the transfer completes.
+ AsyncPixelTransferDelegate* delegate =
+ async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
+ tex_params);
+ texture->SetImmutable(true);
+
+ delegate->AsyncCompressedTexImage2D(
+ tex_params, mem_params,
+ base::Bind(&TextureManager::SetCompressedLevelInfoFromParams,
+ // The callback is only invoked if the transfer delegate still
+ // exists, which implies through manager->texture_ref->state
+ // ownership that both of these pointers are valid.
+ base::Unretained(texture_manager()),
+ base::Unretained(texture_ref), tex_params));
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleAsyncCompressedTexSubImage2DCHROMIUM(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ const gles2::cmds::AsyncCompressedTexSubImage2DCHROMIUM& c =
+ *static_cast<const gles2::cmds::AsyncCompressedTexSubImage2DCHROMIUM*>(
+ cmd_data);
+ TRACE_EVENT0("gpu",
+ "GLES2DecoderImpl::HandleAsyncCompressedTexSubImage2DCHROMIUM");
+ GLenum target = static_cast<GLenum>(c.target);
+ GLint level = static_cast<GLint>(c.level);
+ GLint xoffset = static_cast<GLint>(c.xoffset);
+ GLint yoffset = static_cast<GLint>(c.yoffset);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLenum format = static_cast<GLenum>(c.format);
+ GLsizei image_size = static_cast<GLsizei>(c.imagesize);
+ uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
+ uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
+ uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
+
+ base::ScopedClosureRunner scoped_completion_callback;
+ if (async_upload_token) {
+ base::Closure completion_closure = AsyncUploadTokenCompletionClosure(
+ async_upload_token, sync_data_shm_id, sync_data_shm_offset);
+ if (completion_closure.is_null())
+ return error::kInvalidArguments;
+
+ scoped_completion_callback.Reset(completion_closure);
+ }
+
+ const void* pixels = GetSharedMemoryAs<const void*>(
+ c.data_shm_id, c.data_shm_offset, image_size);
+
+ // All the normal glCompressedTexSubImage2D validation.
+ error::Error error = error::kNoError;
+ if (!ValidateCompressedTexSubImage2D(
+ &error, "glAsyncCompressedTexSubImage2DCHROMIUM", target, level,
+ xoffset, yoffset, width, height, format, image_size, pixels)) {
+ return error;
+ }
+
+ // Extra async validation.
+ TextureRef* texture_ref =
+ texture_manager()->GetTextureInfoForTarget(&state_, target);
+ Texture* texture = texture_ref->texture();
+ if (!ValidateAsyncTransfer("glAsyncCompressedTexSubImage2DCHROMIUM",
+ texture_ref, target, level, pixels))
+ return error::kNoError;
+
+ // Guarantee async textures are always 'cleared' as follows:
+ // - AsyncCompressedTexImage2D can not redefine an existing texture
+ // - AsyncCompressedTexImage2D must initialize the entire image via non-null
+ // buffer.
+ // - AsyncCompressedTexSubImage2D clears synchronously if not already cleared.
+ // - Textures become immutable after an async call.
+ // This way we know in all cases that an async texture is always clear.
+ if (!texture->SafeToRenderFrom()) {
+ if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
+ level)) {
+ LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY,
+ "glAsyncCompressedTexSubImage2DCHROMIUM",
+ "dimensions too big");
+ return error::kNoError;
+ }
+ }
+
+ // Setup the parameters.
+ AsyncCompressedTexSubImage2DParams tex_params = {target,
+ level,
+ xoffset,
+ yoffset,
+ width,
+ height,
+ static_cast<GLenum>(format),
+ image_size};
+ AsyncMemoryParams mem_params(GetSharedMemoryBuffer(c.data_shm_id),
+ c.data_shm_offset, image_size);
+ AsyncPixelTransferDelegate* delegate =
+ async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
+ if (!delegate) {
+ // TODO(epenner): We may want to enforce exclusive use
+ // of async APIs in which case this should become an error,
+ // (the texture should have been async defined).
+ AsyncCompressedTexImage2DParams define_params = {
+ target, level, 0, 0, 0, 0, 0};
+ texture->GetLevelSize(target, level, &define_params.width,
+ &define_params.height);
+ GLenum dummy_type;
+ texture->GetLevelType(target, level, &dummy_type,
+ &define_params.internal_format);
+
+ // Set up the async state if needed, and make the texture
+ // immutable so the async state stays valid.
+ delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
+ texture_ref, define_params);
+ texture->SetImmutable(true);
+ }
+
+ delegate->AsyncCompressedTexSubImage2D(tex_params, mem_params);
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
uint32 immediate_data_size,
const void* cmd_data) {
« no previous file with comments | « gpu/command_buffer/service/feature_info.cc ('k') | gpu/command_buffer/service/gles2_cmd_decoder_autogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698