diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrGpu.cpp | 17 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 35 | ||||
-rw-r--r-- | src/gpu/GrResourceProvider.cpp | 10 | ||||
-rw-r--r-- | src/gpu/GrResourceProvider.h | 1 | ||||
-rw-r--r-- | src/gpu/GrTest.cpp | 9 | ||||
-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 |
9 files changed, 172 insertions, 44 deletions
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index e2457ce31e..2815f612d6 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -334,7 +334,7 @@ bool GrGpu::writePixels(GrSurface* surface, int left, int top, int width, int height, GrPixelConfig config, const void* buffer, size_t rowBytes) { - if (!buffer) { + if (!buffer || !surface) { return false; } @@ -346,6 +346,21 @@ bool GrGpu::writePixels(GrSurface* surface, return false; } +bool GrGpu::transferPixels(GrSurface* surface, + int left, int top, int width, int height, + GrPixelConfig config, GrTransferBuffer* buffer, + size_t offset, size_t rowBytes) { + SkASSERT(buffer); + + this->handleDirtyContext(); + if (this->onTransferPixels(surface, left, top, width, height, config, + buffer, offset, rowBytes)) { + fStats.incTransfersToTexture(); + return true; + } + return false; +} + void GrGpu::resolveRenderTarget(GrRenderTarget* target) { SkASSERT(target); this->handleDirtyContext(); diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index d1b0802721..3eaa3fc035 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -129,11 +129,6 @@ public: */ GrIndexBuffer* createIndexBuffer(size_t size, bool dynamic); - enum TransferType { - kCpuToGpu_TransferType, - kGpuToCpu_TransferType - }; - /** * Creates a transfer buffer. * @@ -266,6 +261,25 @@ public: size_t rowBytes); /** + * Updates the pixels in a rectangle of a surface using a GrTransferBuffer + * + * @param surface The surface to write to. + * @param left left edge of the rectangle to write (inclusive) + * @param top top edge of the rectangle to write (inclusive) + * @param width width of rectangle to write in pixels. + * @param height height of rectangle to write in pixels. + * @param config the pixel config of the source buffer + * @param buffer GrTransferBuffer to read pixels from + * @param offset offset from the start of the buffer + * @param rowBytes number of bytes between consecutive rows. Zero + * means rows are tightly packed. + */ + bool transferPixels(GrSurface* surface, + int left, int top, int width, int height, + GrPixelConfig config, GrTransferBuffer* buffer, + size_t offset, size_t rowBytes); + + /** * Clear the passed in render target. Ignores the draw state and clip. */ void clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget); @@ -344,6 +358,7 @@ public: fShaderCompilations = 0; fTextureCreates = 0; fTextureUploads = 0; + fTransfersToTexture = 0; fStencilAttachmentCreates = 0; fNumDraws = 0; } @@ -356,6 +371,8 @@ public: void incTextureCreates() { fTextureCreates++; } int textureUploads() const { return fTextureUploads; } void incTextureUploads() { fTextureUploads++; } + int transfersToTexture() const { return fTransfersToTexture; } + void incTransfersToTexture() { fTransfersToTexture++; } void incStencilAttachmentCreates() { fStencilAttachmentCreates++; } void incNumDraws() { fNumDraws++; } void dump(SkString*); @@ -366,6 +383,7 @@ public: int fShaderCompilations; int fTextureCreates; int fTextureUploads; + int fTransfersToTexture; int fStencilAttachmentCreates; int fNumDraws; #else @@ -375,6 +393,7 @@ public: void incShaderCompilations() {} void incTextureCreates() {} void incTextureUploads() {} + void incTransfersToTexture() {} void incStencilAttachmentCreates() {} void incNumDraws() {} #endif @@ -508,6 +527,12 @@ private: GrPixelConfig config, const void* buffer, size_t rowBytes) = 0; + // overridden by backend-specific derived class to perform the surface write + virtual bool onTransferPixels(GrSurface*, + int left, int top, int width, int height, + GrPixelConfig config, GrTransferBuffer* buffer, + size_t offset, size_t rowBytes) = 0; + // overridden by backend-specific derived class to perform the resolve virtual void onResolveRenderTarget(GrRenderTarget* target) = 0; diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp index 38213e6266..a8bccfe900 100644 --- a/src/gpu/GrResourceProvider.cpp +++ b/src/gpu/GrResourceProvider.cpp @@ -146,6 +146,16 @@ GrVertexBuffer* GrResourceProvider::createVertexBuffer(size_t size, BufferUsage return this->gpu()->createVertexBuffer(size, dynamic); } +GrTransferBuffer* GrResourceProvider::createTransferBuffer(size_t size, TransferType type, + uint32_t flags) { + if (this->isAbandoned()) { + return nullptr; + } + + //bool noPendingIO = SkToBool(flags & kNoPendingIO_Flag); + return this->gpu()->createTransferBuffer(size, type); +} + GrBatchAtlas* GrResourceProvider::createAtlas(GrPixelConfig config, int width, int height, int numPlotsX, int numPlotsY, diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h index 6c5737191b..bffd5724d0 100644 --- a/src/gpu/GrResourceProvider.h +++ b/src/gpu/GrResourceProvider.h @@ -112,6 +112,7 @@ public: }; GrIndexBuffer* createIndexBuffer(size_t size, BufferUsage, uint32_t flags); GrVertexBuffer* createVertexBuffer(size_t size, BufferUsage, uint32_t flags); + GrTransferBuffer* createTransferBuffer(size_t size, TransferType, uint32_t flags); GrTexture* createApproxTexture(const GrSurfaceDesc& desc, uint32_t flags) { SkASSERT(0 == flags || kNoPendingIO_Flag == flags); diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp index 98ebe0621e..03a8d54a6d 100644 --- a/src/gpu/GrTest.cpp +++ b/src/gpu/GrTest.cpp @@ -173,6 +173,7 @@ void GrGpu::Stats::dump(SkString* out) { out->appendf("Shader Compilations: %d\n", fShaderCompilations); out->appendf("Textures Created: %d\n", fTextureCreates); out->appendf("Texture Uploads: %d\n", fTextureUploads); + out->appendf("Transfers to Texture: %d\n", fTransfersToTexture); out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates); out->appendf("Number of draws: %d\n", fNumDraws); } @@ -182,6 +183,7 @@ void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations); keys->push_back(SkString("textures_created")); values->push_back(fTextureCreates); keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads); + keys->push_back(SkString("transfers_to_texture")); values->push_back(fTransfersToTexture); keys->push_back(SkString("stencil_buffer_creates")); values->push_back(fStencilAttachmentCreates); keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws); } @@ -337,6 +339,13 @@ private: return false; } + bool onTransferPixels(GrSurface* surface, + int left, int top, int width, int height, + GrPixelConfig config, GrTransferBuffer* buffer, + size_t offset, size_t rowBytes) override { + return false; + } + void onResolveRenderTarget(GrRenderTarget* target) override { return; } GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*, 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; |