diff options
author | jvanverth <jvanverth@google.com> | 2016-01-05 10:41:27 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-05 10:41:27 -0800 |
commit | 17aa047066eaaa56637c4c2b93c8c4c374127dbf (patch) | |
tree | fd23a2418ee23597760f1906025eaa344a3ac020 /src/gpu/gl | |
parent | 7928ef613f11a3c97fd939090197b8ae2be44b7a (diff) |
More framework support for TransferBuffers
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1534123003
Review URL: https://codereview.chromium.org/1534123003
Diffstat (limited to 'src/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGLBufferImpl.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 126 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 14 | ||||
-rwxr-xr-x | src/gpu/gl/GrGLTransferBuffer.h | 1 |
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; |