aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2016-01-05 10:41:27 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-01-05 10:41:27 -0800
commit17aa047066eaaa56637c4c2b93c8c4c374127dbf (patch)
treefd23a2418ee23597760f1906025eaa344a3ac020 /src/gpu/gl
parent7928ef613f11a3c97fd939090197b8ae2be44b7a (diff)
More framework support for TransferBuffers
Diffstat (limited to 'src/gpu/gl')
-rw-r--r--src/gpu/gl/GrGLBufferImpl.h3
-rw-r--r--src/gpu/gl/GrGLGpu.cpp126
-rw-r--r--src/gpu/gl/GrGLGpu.h14
-rwxr-xr-xsrc/gpu/gl/GrGLTransferBuffer.h1
4 files changed, 106 insertions, 38 deletions
diff --git a/src/gpu/gl/GrGLBufferImpl.h b/src/gpu/gl/GrGLBufferImpl.h
index ef7ce95541..a8f2cced37 100644
--- a/src/gpu/gl/GrGLBufferImpl.h
+++ b/src/gpu/gl/GrGLBufferImpl.h
@@ -46,6 +46,7 @@ public:
GrGLuint bufferID() const { return fDesc.fID; }
size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); }
+ GrGLenum bufferType() const { return fBufferType; }
void* map(GrGLGpu* gpu);
void unmap(GrGLGpu* gpu);
@@ -56,7 +57,7 @@ private:
void validate() const;
Desc fDesc;
- GrGLenum fBufferType; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER
+ GrGLenum fBufferType; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER, e.g.
void* fCPUData;
void* fMapPtr;
size_t fGLSizeInBytes; // In certain cases we make the size of the GL buffer object
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index cbb4360f5d..49b8f3acb8 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -593,11 +593,8 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
return true;
}
-bool GrGLGpu::onWritePixels(GrSurface* surface,
- int left, int top, int width, int height,
- GrPixelConfig config, const void* buffer,
- size_t rowBytes) {
- GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
+static bool check_write_and_transfer_input(GrGLTexture* glTex, GrSurface* surface,
+ GrPixelConfig config) {
if (!glTex) {
return false;
}
@@ -607,11 +604,24 @@ bool GrGLGpu::onWritePixels(GrSurface* surface,
return false;
}
- // Write pixels is only implemented for TEXTURE_2D textures
+ // Write or transfer of pixels is only implemented for TEXTURE_2D textures
if (GR_GL_TEXTURE_2D != glTex->target()) {
return false;
}
+ return true;
+}
+
+bool GrGLGpu::onWritePixels(GrSurface* surface,
+ int left, int top, int width, int height,
+ GrPixelConfig config, const void* buffer,
+ 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()));
@@ -619,11 +629,11 @@ bool GrGLGpu::onWritePixels(GrSurface* surface,
if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) {
// We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixels()
SkASSERT(config == glTex->desc().fConfig);
- success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), buffer, false, left,
- top, width, height);
+ success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), buffer,
+ kWrite_UploadType, left, top, width, height);
} else {
- success = this->uploadTexData(glTex->desc(), glTex->target(), false, left, top, width,
- height, config, buffer, rowBytes);
+ success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_UploadType,
+ left, top, width, height, config, buffer, rowBytes);
}
if (success) {
@@ -634,6 +644,43 @@ bool GrGLGpu::onWritePixels(GrSurface* surface,
return false;
}
+bool GrGLGpu::onTransferPixels(GrSurface* surface,
+ int left, int top, int width, int height,
+ GrPixelConfig config, GrTransferBuffer* buffer,
+ size_t offset, size_t rowBytes) {
+ GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
+
+ if (!check_write_and_transfer_input(glTex, surface, config)) {
+ return false;
+ }
+
+ // For the moment, can't transfer compressed data
+ if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) {
+ return false;
+ }
+
+ this->setScratchTextureUnit();
+ GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
+
+ SkASSERT(!buffer->isMapped());
+ GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer);
+ // bind the transfer buffer
+ SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() ||
+ GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType());
+ GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID()));
+
+ bool success = false;
+ success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_UploadType,
+ left, top, width, height, config, buffer, rowBytes);
+
+ if (success) {
+ glTex->texturePriv().dirtyMipMaps(true);
+ return true;
+ }
+
+ return false;
+}
+
// For GL_[UN]PACK_ALIGNMENT.
static inline GrGLint config_alignment(GrPixelConfig config) {
SkASSERT(!GrPixelConfigIsCompressed(config));
@@ -666,12 +713,13 @@ static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc,
bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
GrGLenum target,
- bool isNewTexture,
+ UploadType uploadType,
int left, int top, int width, int height,
GrPixelConfig dataConfig,
- const void* data,
+ const void* dataOrOffset,
size_t rowBytes) {
- SkASSERT(data || isNewTexture);
+ SkASSERT(dataOrOffset || kNewTexture_UploadType == uploadType ||
+ kTransfer_UploadType == uploadType);
// If we're uploading compressed data then we should be using uploadCompressedTexData
SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
@@ -680,7 +728,7 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
size_t bpp = GrBytesPerPixel(dataConfig);
if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
- &width, &height, &data, &rowBytes)) {
+ &width, &height, &dataOrOffset, &rowBytes)) {
return false;
}
size_t trimRowBytes = width * bpp;
@@ -711,7 +759,7 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
bool restoreGLRowLength = false;
bool swFlipY = false;
bool glFlipY = false;
- if (data) {
+ if (dataOrOffset) {
if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
if (this->glCaps().unpackFlipYSupport()) {
glFlipY = true;
@@ -726,11 +774,11 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
restoreGLRowLength = true;
}
- } else {
+ } else if (kTransfer_UploadType != uploadType) {
if (trimRowBytes != rowBytes || swFlipY) {
// copy data into our new storage, skipping the trailing bytes
size_t trimSize = height * trimRowBytes;
- const char* src = (const char*)data;
+ const char* src = (const char*)dataOrOffset;
if (swFlipY) {
src += (height - 1) * rowBytes;
}
@@ -745,8 +793,10 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
dst += trimRowBytes;
}
// now point data to our copied version
- data = tempStorage.get();
+ dataOrOffset = tempStorage.get();
}
+ } else {
+ return false;
}
if (glFlipY) {
GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
@@ -754,14 +804,15 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(dataConfig)));
}
bool succeeded = true;
- if (isNewTexture) {
- if (data && !(0 == left && 0 == top && desc.fWidth == width && desc.fHeight == height)) {
+ if (kNewTexture_UploadType == uploadType) {
+ if (dataOrOffset &&
+ !(0 == left && 0 == top && desc.fWidth == width && desc.fHeight == height)) {
succeeded = false;
} else {
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
GL_ALLOC_CALL(this->glInterface(), TexImage2D(target, 0, internalFormat, desc.fWidth,
desc.fHeight, 0, externalFormat,
- externalType, data));
+ externalType, dataOrOffset));
GrGLenum error = check_alloc_error(desc, this->glInterface());
if (error != GR_GL_NO_ERROR) {
succeeded = false;
@@ -775,7 +826,7 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
0, // level
left, top,
width, height,
- externalFormat, externalType, data));
+ externalFormat, externalType, dataOrOffset));
}
if (restoreGLRowLength) {
@@ -796,10 +847,11 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
GrGLenum target,
const void* data,
- bool isNewTexture,
+ UploadType uploadType,
int left, int top, int width, int height) {
SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
- SkASSERT(data || isNewTexture);
+ SkASSERT(kTransfer_UploadType != uploadType &&
+ (data || kNewTexture_UploadType != uploadType));
// No support for software flip y, yet...
SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin);
@@ -830,7 +882,7 @@ bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
// sized vs base internal format distinction for compressed textures.
GrGLenum internalFormat =this->glCaps().configGLFormats(desc.fConfig).fSizedInternalFormat;
- if (isNewTexture) {
+ if (kNewTexture_UploadType == uploadType) {
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
GL_ALLOC_CALL(this->glInterface(),
CompressedTexImage2D(target,
@@ -1076,7 +1128,7 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
GL_CALL(TexParameteri(idDesc.fInfo.fTarget,
GR_GL_TEXTURE_WRAP_T,
initialTexParams.fWrapT));
- if (!this->uploadTexData(desc, idDesc.fInfo.fTarget, true, 0, 0,
+ if (!this->uploadTexData(desc, idDesc.fInfo.fTarget, kNewTexture_UploadType, 0, 0,
desc.fWidth, desc.fHeight,
desc.fConfig, srcData, rowBytes)) {
GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID));
@@ -1438,16 +1490,17 @@ GrTransferBuffer* GrGLGpu::onCreateTransferBuffer(size_t size, TransferType xfer
if (desc.fID) {
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
// make sure driver can allocate memory for this bmapuffer
- GrGLenum type;
+ GrGLenum target;
if (GrGLCaps::kChromium_TransferBufferType == xferBufferType) {
- type = toGpu ? GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
+ target = toGpu ? GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
: GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM;
} else {
SkASSERT(GrGLCaps::kPBO_TransferBufferType == xferBufferType);
- type = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUFFER;
+ target = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUFFER;
}
- GL_ALLOC_CALL(this->glInterface(),
- BufferData(type,
+ GL_CALL(BindBuffer(target, desc.fID));
+ GL_ALLOC_CALL(this->glInterface(),
+ BufferData(target,
(GrGLsizeiptr) desc.fSizeInBytes,
nullptr, // data ptr
(toGpu ? GR_GL_STREAM_DRAW : GR_GL_STREAM_READ)));
@@ -1455,7 +1508,7 @@ GrTransferBuffer* GrGLGpu::onCreateTransferBuffer(size_t size, TransferType xfer
GL_CALL(DeleteBuffers(1, &desc.fID));
return nullptr;
}
- GrTransferBuffer* transferBuffer = new GrGLTransferBuffer(this, desc, type);
+ GrTransferBuffer* transferBuffer = new GrGLTransferBuffer(this, desc, target);
return transferBuffer;
}
@@ -1655,11 +1708,14 @@ void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage
if (currentSize != requestedSize) {
GL_CALL(BufferData(type, requestedSize, nullptr, glUsage));
}
- static const GrGLbitfield kWriteAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT |
- GR_GL_MAP_WRITE_BIT;
+ GrGLbitfield writeAccess = GR_GL_MAP_WRITE_BIT;
+ // TODO: allow the client to specify invalidation in the stream draw case
+ if (GrGLBufferImpl::kStreamDraw_Usage != usage) {
+ writeAccess |= GR_GL_MAP_INVALIDATE_BUFFER_BIT;
+ }
GL_CALL_RET(mapPtr, MapBufferRange(type, 0, requestedSize, readOnly ?
GR_GL_MAP_READ_BIT :
- kWriteAccess));
+ writeAccess));
break;
}
case GrGLCaps::kChromium_MapBufferType:
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 8c127f6419..532a864f07 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -172,6 +172,11 @@ private:
GrPixelConfig config, const void* buffer,
size_t rowBytes) override;
+ bool onTransferPixels(GrSurface*,
+ int left, int top, int width, int height,
+ GrPixelConfig config, GrTransferBuffer* buffer,
+ size_t offset, size_t rowBytes) override;
+
void onResolveRenderTarget(GrRenderTarget* target) override;
void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override;
@@ -284,9 +289,14 @@ private:
void flushHWAAState(GrRenderTarget* rt, bool useHWAA);
// 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
+ };
bool uploadTexData(const GrSurfaceDesc& desc,
GrGLenum target,
- bool isNewTexture,
+ UploadType uploadType,
int left, int top, int width, int height,
GrPixelConfig dataConfig,
const void* data,
@@ -301,7 +311,7 @@ private:
bool uploadCompressedTexData(const GrSurfaceDesc& desc,
GrGLenum target,
const void* data,
- bool isNewTexture = true,
+ UploadType uploadType = kNewTexture_UploadType,
int left = 0, int top = 0,
int width = -1, int height = -1);
diff --git a/src/gpu/gl/GrGLTransferBuffer.h b/src/gpu/gl/GrGLTransferBuffer.h
index ff9caeea74..e01d4447df 100755
--- a/src/gpu/gl/GrGLTransferBuffer.h
+++ b/src/gpu/gl/GrGLTransferBuffer.h
@@ -23,6 +23,7 @@ public:
GrGLuint bufferID() const { return fImpl.bufferID(); }
size_t baseOffset() const { return fImpl.baseOffset(); }
+ GrGLenum bufferType() const { return fImpl.bufferType(); }
protected:
void onAbandon() override;