aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2017-06-21 10:52:43 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-21 15:28:50 +0000
commitf7037d003c936f59e4d02244821e223c2e7af8e8 (patch)
tree88949675e25db5cd8c6d136b2b59f19d9bcf2263 /src/gpu/gl
parent44eb6d9c5ab280cacdfec734e3f3e56285f1f87f (diff)
Clean up onTransferPixels
Bug: skia:5126 Change-Id: I323c50e7854744302007b4ae7bd25e5742c14cbc Reviewed-on: https://skia-review.googlesource.com/19055 Commit-Queue: Jim Van Verth <jvanverth@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
Diffstat (limited to 'src/gpu/gl')
-rw-r--r--src/gpu/gl/GrGLBuffer.cpp6
-rw-r--r--src/gpu/gl/GrGLCaps.cpp10
-rw-r--r--src/gpu/gl/GrGLGpu.cpp151
-rw-r--r--src/gpu/gl/GrGLGpu.h7
4 files changed, 114 insertions, 60 deletions
diff --git a/src/gpu/gl/GrGLBuffer.cpp b/src/gpu/gl/GrGLBuffer.cpp
index 7dfc6b81e7..180dc39958 100644
--- a/src/gpu/gl/GrGLBuffer.cpp
+++ b/src/gpu/gl/GrGLBuffer.cpp
@@ -31,6 +31,12 @@
GrGLBuffer* GrGLBuffer::Create(GrGLGpu* gpu, size_t size, GrBufferType intendedType,
GrAccessPattern accessPattern, const void* data) {
+ if (gpu->glCaps().transferBufferType() == GrGLCaps::kNone_TransferBufferType &&
+ (kXferCpuToGpu_GrBufferType == intendedType ||
+ kXferGpuToCpu_GrBufferType == intendedType)) {
+ return nullptr;
+ }
+
sk_sp<GrGLBuffer> buffer(new GrGLBuffer(gpu, size, intendedType, accessPattern, data));
if (0 == buffer->bufferID()) {
return nullptr;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 95791f12bb..faea4e6395 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -457,10 +457,14 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
fTransferBufferType = kPBO_TransferBufferType;
}
} else {
- if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_NV_pixel_buffer_object")) {
+ if (version >= GR_GL_VER(3, 0) ||
+ (ctxInfo.hasExtension("GL_NV_pixel_buffer_object") &&
+ // GL_EXT_unpack_subimage needed to support subtexture rectangles
+ ctxInfo.hasExtension("GL_EXT_unpack_subimage"))) {
fTransferBufferType = kPBO_TransferBufferType;
- } else if (ctxInfo.hasExtension("GL_CHROMIUM_pixel_transfer_buffer_object")) {
- fTransferBufferType = kChromium_TransferBufferType;
+// TODO: get transfer buffers working in Chrome
+// } else if (ctxInfo.hasExtension("GL_CHROMIUM_pixel_transfer_buffer_object")) {
+// fTransferBufferType = kChromium_TransferBufferType;
}
}
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index e5e8841c37..f63fc253a3 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -783,36 +783,6 @@ bool GrGLGpu::onWritePixels(GrSurface* surface,
left, top, width, height, config, texels);
}
-bool GrGLGpu::onTransferPixels(GrSurface* surface,
- int left, int top, int width, int height,
- GrPixelConfig config, GrBuffer* transferBuffer,
- size_t offset, size_t rowBytes) {
- GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
-
- if (!check_write_and_transfer_input(glTex, surface, config)) {
- return false;
- }
-
- this->setScratchTextureUnit();
- GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
-
- SkASSERT(!transferBuffer->isMapped());
- SkASSERT(!transferBuffer->isCPUBacked());
- const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer);
- this->bindBuffer(kXferCpuToGpu_GrBufferType, glBuffer);
-
- bool success = false;
- GrMipLevel mipLevel;
- mipLevel.fPixels = transferBuffer;
- mipLevel.fRowBytes = rowBytes;
- SkSTArray<1, GrMipLevel> texels;
- texels.push_back(mipLevel);
- success = this->uploadTexData(glTex->config(), glTex->width(), glTex->height(), glTex->origin(),
- glTex->target(), kTransfer_UploadType, left, top, width, height,
- config, texels);
- return success;
-}
-
// For GL_[UN]PACK_ALIGNMENT.
static inline GrGLint config_alignment(GrPixelConfig config) {
switch (config) {
@@ -839,6 +809,78 @@ static inline GrGLint config_alignment(GrPixelConfig config) {
return 0;
}
+bool GrGLGpu::onTransferPixels(GrTexture* texture,
+ int left, int top, int width, int height,
+ GrPixelConfig config, GrBuffer* transferBuffer,
+ size_t offset, size_t rowBytes) {
+ GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
+ GrPixelConfig texConfig = glTex->config();
+ SkASSERT(this->caps()->isConfigTexturable(texConfig));
+
+ if (!check_write_and_transfer_input(glTex, texture, config)) {
+ return false;
+ }
+
+ if (width <= 0 || width > SK_MaxS32 || height <= 0 || height > SK_MaxS32) {
+ return false;
+ }
+
+ this->setScratchTextureUnit();
+ GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
+
+ SkASSERT(!transferBuffer->isMapped());
+ SkASSERT(!transferBuffer->isCPUBacked());
+ const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer);
+ this->bindBuffer(kXferCpuToGpu_GrBufferType, glBuffer);
+
+ size_t bpp = GrBytesPerPixel(config);
+ const size_t trimRowBytes = width * bpp;
+ const void* pixels = (void*)offset;
+ if (!GrSurfacePriv::AdjustWritePixelParams(glTex->width(), glTex->height(), bpp,
+ &left, &top,
+ &width, &height,
+ &pixels,
+ &rowBytes)) {
+ return false;
+ }
+ if (width < 0 || width < 0) {
+ return false;
+ }
+
+ bool restoreGLRowLength = false;
+ if (trimRowBytes != rowBytes) {
+ // we should have checked for this support already
+ SkASSERT(this->glCaps().unpackRowLengthSupport());
+ GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowBytes / bpp));
+ restoreGLRowLength = true;
+ }
+
+ // Internal format comes from the texture desc.
+ GrGLenum internalFormat;
+ // External format and type come from the upload data.
+ GrGLenum externalFormat;
+ GrGLenum externalType;
+ if (!this->glCaps().getTexImageFormats(texConfig, config, &internalFormat,
+ &externalFormat, &externalType)) {
+ return false;
+ }
+
+ GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(texConfig)));
+ GL_CALL(TexSubImage2D(glTex->target(),
+ 0,
+ left, top,
+ width,
+ height,
+ externalFormat, externalType,
+ pixels));
+
+ if (restoreGLRowLength) {
+ GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
+ }
+
+ return true;
+}
+
/**
* Creates storage space for the texture and fills it with texels.
*
@@ -971,6 +1013,13 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
const SkTArray<GrMipLevel>& texels) {
SkASSERT(this->caps()->isConfigTexturable(texConfig));
+ // unbind any previous transfer buffer
+ auto& xferBufferState = fHWBufferState[kXferCpuToGpu_GrBufferType];
+ if (!xferBufferState.fBoundBufferUniqueID.isInvalid()) {
+ GL_CALL(BindBuffer(xferBufferState.fGLTarget, 0));
+ xferBufferState.invalidate();
+ }
+
// texels is const.
// But we may need to flip the texture vertically to prepare it.
// Rather than flip in place and alter the incoming data,
@@ -980,7 +1029,7 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
currentMipLevel--) {
- SkASSERT(texelsShallowCopy[currentMipLevel].fPixels || kTransfer_UploadType == uploadType);
+ SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
}
const GrGLInterface* interface = this->glInterface();
@@ -1086,30 +1135,26 @@ bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight
GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
restoreGLRowLength = true;
}
- } else if (kTransfer_UploadType != uploadType) {
- if (trimRowBytes != rowBytes || swFlipY) {
- // copy data into our new storage, skipping the trailing bytes
- const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
- if (swFlipY && currentHeight >= 1) {
- src += (currentHeight - 1) * rowBytes;
- }
- char* dst = buffer + individual_mip_offsets[currentMipLevel];
- for (int y = 0; y < currentHeight; y++) {
- memcpy(dst, src, trimRowBytes);
- if (swFlipY) {
- src -= rowBytes;
- } else {
- src += rowBytes;
- }
- dst += trimRowBytes;
+ } else if (trimRowBytes != rowBytes || swFlipY) {
+ // copy data into our new storage, skipping the trailing bytes
+ const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
+ if (swFlipY && currentHeight >= 1) {
+ src += (currentHeight - 1) * rowBytes;
+ }
+ char* dst = buffer + individual_mip_offsets[currentMipLevel];
+ for (int y = 0; y < currentHeight; y++) {
+ memcpy(dst, src, trimRowBytes);
+ if (swFlipY) {
+ src -= rowBytes;
+ } else {
+ src += rowBytes;
}
- // now point data to our copied version
- texelsShallowCopy[currentMipLevel].fPixels = buffer +
- individual_mip_offsets[currentMipLevel];
- texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes;
+ dst += trimRowBytes;
}
- } else {
- return false;
+ // now point data to our copied version
+ texelsShallowCopy[currentMipLevel].fPixels = buffer +
+ individual_mip_offsets[currentMipLevel];
+ texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes;
}
}
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 80a12eb7cc..5897f5dae5 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -247,7 +247,7 @@ private:
GrPixelConfig config,
const SkTArray<GrMipLevel>& texels) override;
- bool onTransferPixels(GrSurface*,
+ bool onTransferPixels(GrTexture*,
int left, int top, int width, int height,
GrPixelConfig config, GrBuffer* transferBuffer,
size_t offset, size_t rowBytes) override;
@@ -373,9 +373,8 @@ private:
// helper for onCreateTexture and writeTexturePixels
enum UploadType {
- kNewTexture_UploadType, // we are creating a new texture
- kWrite_UploadType, // we are using TexSubImage2D to copy data to an existing texture
- kTransfer_UploadType, // we are using a transfer buffer to copy data
+ kNewTexture_UploadType, // we are creating a new texture
+ kWrite_UploadType, // we are using TexSubImage2D to copy data to an existing texture
};
bool uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight,
GrSurfaceOrigin texOrigin, GrGLenum target, UploadType uploadType, int left,