diff --git a/.idea/misc.xml b/.idea/misc.xml index 91398c79..ae66e0cd 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,20 +3,21 @@ + + + - - - - - - - - + + + + + + diff --git a/src/gpu/Gpu.h b/src/gpu/Gpu.h index b25cc244..b3b9faed 100644 --- a/src/gpu/Gpu.h +++ b/src/gpu/Gpu.h @@ -34,10 +34,12 @@ class Gpu { public: virtual ~Gpu() = default; - Context* context() { - return _context; + Context* getContext() { + return context; } + virtual std::shared_ptr getRenderPass() = 0; + virtual std::unique_ptr createSampler(int width, int height, PixelFormat format, int mipLevelCount) = 0; @@ -55,9 +57,6 @@ class Gpu { virtual bool waitSemaphore(const Semaphore* semaphore) = 0; - virtual RenderPass* getRenderPass(std::shared_ptr renderTarget, - std::shared_ptr renderTargetTexture) = 0; - virtual bool submitToGpu(bool syncCpu) = 0; virtual void submit(RenderPass* renderPass) = 0; @@ -65,11 +64,11 @@ class Gpu { void regenerateMipMapLevels(const TextureSampler* sampler); protected: - explicit Gpu(Context* context) : _context(context) { + Context* context; + + explicit Gpu(Context* context) : context(context) { } virtual void onRegenerateMipMapLevels(const TextureSampler* sampler) = 0; - - Context* _context; }; } // namespace tgfx diff --git a/src/gpu/RenderPass.cpp b/src/gpu/RenderPass.cpp index 4e0b8a1b..fbf9352a 100644 --- a/src/gpu/RenderPass.cpp +++ b/src/gpu/RenderPass.cpp @@ -19,11 +19,22 @@ #include "RenderPass.h" namespace tgfx { -void RenderPass::begin() { +bool RenderPass::begin(std::shared_ptr renderTargetProxy) { + if (renderTargetProxy == nullptr) { + return false; + } + _renderTarget = renderTargetProxy->getRenderTarget(); + if (_renderTarget == nullptr) { + return false; + } + _renderTargetTexture = renderTargetProxy->getTexture(); drawPipelineStatus = DrawPipelineStatus::NotConfigured; + return true; } void RenderPass::end() { + _renderTarget = nullptr; + _renderTargetTexture = nullptr; resetActiveBuffers(); } diff --git a/src/gpu/RenderPass.h b/src/gpu/RenderPass.h index c03db06c..dc05e3f4 100644 --- a/src/gpu/RenderPass.h +++ b/src/gpu/RenderPass.h @@ -25,6 +25,7 @@ #include "gpu/RenderTarget.h" #include "gpu/processors/GeometryProcessor.h" #include "gpu/proxies/GpuBufferProxy.h" +#include "gpu/proxies/RenderTargetProxy.h" #include "tgfx/core/BlendMode.h" #include "tgfx/core/Color.h" #include "tgfx/gpu/Context.h" @@ -40,11 +41,10 @@ enum class PrimitiveType { class RenderPass { public: - explicit RenderPass(Context* context) : _context(context) { - } + virtual ~RenderPass() = default; - Context* context() { - return _context; + Context* getContext() { + return context; } std::shared_ptr renderTarget() { @@ -55,9 +55,7 @@ class RenderPass { return _renderTargetTexture; } - virtual ~RenderPass() = default; - - void begin(); + bool begin(std::shared_ptr renderTargetProxy); void end(); void bindProgramAndScissorClip(const ProgramInfo* programInfo, const Rect& drawBounds); void bindBuffers(std::shared_ptr indexBuffer, std::shared_ptr vertexBuffer); @@ -66,6 +64,9 @@ class RenderPass { void clear(const Rect& scissor, Color color); protected: + explicit RenderPass(Context* context) : context(context) { + } + virtual bool onBindProgramAndScissorClip(const ProgramInfo* programInfo, const Rect& drawBounds) = 0; virtual void onBindBuffers(std::shared_ptr indexBuffer, @@ -74,7 +75,7 @@ class RenderPass { virtual void onDrawIndexed(PrimitiveType primitiveType, size_t baseIndex, size_t indexCount) = 0; virtual void onClear(const Rect& scissor, Color color) = 0; - Context* _context = nullptr; + Context* context = nullptr; std::shared_ptr _renderTarget = nullptr; std::shared_ptr _renderTargetTexture = nullptr; Program* _program = nullptr; diff --git a/src/gpu/ops/DrawOp.cpp b/src/gpu/ops/DrawOp.cpp index 8fbf0d4d..d2ae6adf 100644 --- a/src/gpu/ops/DrawOp.cpp +++ b/src/gpu/ops/DrawOp.cpp @@ -23,7 +23,8 @@ namespace tgfx { static DstTextureInfo CreateDstTextureInfo(RenderPass* renderPass, Rect dstRect) { DstTextureInfo dstTextureInfo = {}; - if (renderPass->context()->caps()->textureBarrierSupport && renderPass->renderTargetTexture()) { + auto context = renderPass->getContext(); + if (context->caps()->textureBarrierSupport && renderPass->renderTargetTexture()) { dstTextureInfo.texture = renderPass->renderTargetTexture(); dstTextureInfo.requiresBarrier = true; return dstTextureInfo; @@ -40,7 +41,7 @@ static DstTextureInfo CreateDstTextureInfo(RenderPass* renderPass, Rect dstRect) } dstRect.roundOut(); dstTextureInfo.offset = {dstRect.x(), dstRect.y()}; - auto dstTexture = Texture::MakeRGBA(renderPass->context(), static_cast(dstRect.width()), + auto dstTexture = Texture::MakeRGBA(context, static_cast(dstRect.width()), static_cast(dstRect.height()), false, renderPass->renderTarget()->origin()); if (dstTexture == nullptr) { @@ -48,8 +49,8 @@ static DstTextureInfo CreateDstTextureInfo(RenderPass* renderPass, Rect dstRect) return {}; } dstTextureInfo.texture = dstTexture; - renderPass->context()->gpu()->copyRenderTargetToTexture(renderPass->renderTarget().get(), - dstTexture.get(), dstRect, Point::Zero()); + context->gpu()->copyRenderTargetToTexture(renderPass->renderTarget().get(), dstTexture.get(), + dstRect, Point::Zero()); return dstTextureInfo; } @@ -62,7 +63,7 @@ std::unique_ptr DrawOp::createPipeline(RenderPass* renderPass, std::move(_masks.begin(), _masks.end(), fragmentProcessors.begin() + static_cast(numColorProcessors)); DstTextureInfo dstTextureInfo = {}; - auto caps = renderPass->context()->caps(); + auto caps = renderPass->getContext()->caps(); if (!BlendModeAsCoeff(blendMode) && !caps->frameBufferFetchSupport) { dstTextureInfo = CreateDstTextureInfo(renderPass, bounds()); } diff --git a/src/gpu/ops/RRectOp.cpp b/src/gpu/ops/RRectOp.cpp index 67d6c519..65339802 100644 --- a/src/gpu/ops/RRectOp.cpp +++ b/src/gpu/ops/RRectOp.cpp @@ -330,7 +330,7 @@ void RRectOp::execute(RenderPass* renderPass) { auto pipeline = createPipeline( renderPass, EllipseGeometryProcessor::Make(renderPass->renderTarget()->width(), renderPass->renderTarget()->height(), false, - UseScale(renderPass->context()), localMatrix)); + UseScale(renderPass->getContext()), localMatrix)); renderPass->bindProgramAndScissorClip(pipeline.get(), scissorRect()); renderPass->bindBuffers(indexBuffer, vertexBuffer); renderPass->drawIndexed(PrimitiveType::Triangles, 0, rRectPaints.size() * kIndicesPerFillRRect); diff --git a/src/gpu/tasks/OpsRenderTask.cpp b/src/gpu/tasks/OpsRenderTask.cpp index 2b507784..0d2c31bd 100644 --- a/src/gpu/tasks/OpsRenderTask.cpp +++ b/src/gpu/tasks/OpsRenderTask.cpp @@ -29,6 +29,7 @@ void OpsRenderTask::addOp(std::unique_ptr op) { } void OpsRenderTask::prepare(Context* context) { + renderPass = context->gpu()->getRenderPass(); for (auto& op : ops) { op->prepare(context); } @@ -38,20 +39,16 @@ bool OpsRenderTask::execute(Gpu* gpu) { if (ops.empty()) { return false; } - auto renderTarget = renderTargetProxy->getRenderTarget(); - auto texture = renderTargetProxy->getTexture(); - auto renderPass = gpu->getRenderPass(renderTarget, texture); - if (renderPass == nullptr) { - LOGE("OpsTask::execute() Failed to create render pass!"); + if (!renderPass->begin(renderTargetProxy)) { + LOGE("OpsTask::execute() Failed to initialize the render pass!"); return false; } - renderPass->begin(); auto tempOps = std::move(ops); for (auto& op : tempOps) { - op->execute(renderPass); + op->execute(renderPass.get()); } + gpu->submit(renderPass.get()); renderPass->end(); - gpu->submit(renderPass); return true; } } // namespace tgfx diff --git a/src/gpu/tasks/OpsRenderTask.h b/src/gpu/tasks/OpsRenderTask.h index d68a61c0..c63147d5 100644 --- a/src/gpu/tasks/OpsRenderTask.h +++ b/src/gpu/tasks/OpsRenderTask.h @@ -36,6 +36,7 @@ class OpsRenderTask : public RenderTask { bool execute(Gpu* gpu) override; private: - std::vector> ops; + std::shared_ptr renderPass = nullptr; + std::vector> ops = {}; }; } // namespace tgfx diff --git a/src/gpu/tasks/RenderTargetCreateTask.cpp b/src/gpu/tasks/RenderTargetCreateTask.cpp index 6e7ac40c..02fe0a30 100644 --- a/src/gpu/tasks/RenderTargetCreateTask.cpp +++ b/src/gpu/tasks/RenderTargetCreateTask.cpp @@ -39,16 +39,16 @@ RenderTargetCreateTask::RenderTargetCreateTask(ResourceKey strongKey, ResourceKe std::shared_ptr RenderTargetCreateTask::onMakeResource(Context* context) { auto texture = Resource::Get(context, textureKey); if (texture == nullptr) { - LOGE("RenderTargetCreateTask::onMakeResource() Failed to get texture!"); + LOGE("RenderTargetCreateTask::onMakeResource() Failed to get the associated texture!"); return nullptr; } if (texture->getSampler()->format != pixelFormat) { - LOGE("RenderTargetCreateTask::onMakeResource() texture format mismatch!"); + LOGE("RenderTargetCreateTask::onMakeResource() the texture format mismatch!"); return nullptr; } auto renderTarget = RenderTarget::MakeFrom(texture.get(), sampleCount); if (renderTarget == nullptr) { - LOGE("RenderTargetCreateTask::onMakeResource() Failed to create render target!"); + LOGE("RenderTargetCreateTask::onMakeResource() Failed to create the render target!"); } return renderTarget; } diff --git a/src/gpu/tasks/TextureCreateTask.cpp b/src/gpu/tasks/TextureCreateTask.cpp index 544ecfa8..a389f928 100644 --- a/src/gpu/tasks/TextureCreateTask.cpp +++ b/src/gpu/tasks/TextureCreateTask.cpp @@ -31,7 +31,7 @@ class EmptyTextureTask : public TextureCreateTask { std::shared_ptr onMakeResource(Context* context) override { auto texture = Texture::MakeFormat(context, width, height, format, mipMapped, origin); if (texture == nullptr) { - LOGE("EmptyTextureTask::onMakeResource() Failed to create texture!"); + LOGE("EmptyTextureTask::onMakeResource() Failed to create the texture!"); } return texture; } @@ -66,12 +66,12 @@ class ImageDecoderTask : public TextureCreateTask { } auto imageBuffer = decoder->decode(); if (imageBuffer == nullptr) { - LOGE("ImageDecoderTask::onMakeResource() Failed to decode image!"); + LOGE("ImageDecoderTask::onMakeResource() Failed to decode the image!"); return nullptr; } auto texture = Texture::MakeFrom(context, imageBuffer, mipMapped); if (texture == nullptr) { - LOGE("ImageDecoderTask::onMakeResource() Failed to create texture!"); + LOGE("ImageDecoderTask::onMakeResource() Failed to create the texture!"); } else { // Free the decoded image buffer immediately to reduce memory pressure. decoder = nullptr; diff --git a/src/opengl/GLGpu.cpp b/src/opengl/GLGpu.cpp index 98545951..03ccf2ab 100644 --- a/src/opengl/GLGpu.cpp +++ b/src/opengl/GLGpu.cpp @@ -27,14 +27,21 @@ std::unique_ptr GLGpu::Make(Context* context) { return std::unique_ptr(new GLGpu(context)); } +std::shared_ptr GLGpu::getRenderPass() { + if (renderPass == nullptr) { + renderPass = std::make_shared(context); + } + return renderPass; +} + std::unique_ptr GLGpu::createSampler(int width, int height, PixelFormat format, int mipLevelCount) { // Texture memory must be allocated first on the web platform then can write pixels. DEBUG_ASSERT(mipLevelCount > 0); // Clear the previously generated GLError, causing the subsequent CheckGLError to return an // incorrect result. - CheckGLError(_context); - auto gl = GLFunctions::Get(_context); + CheckGLError(context); + auto gl = GLFunctions::Get(context); auto sampler = std::make_unique(); gl->genTextures(1, &(sampler->id)); if (sampler->id == 0) { @@ -48,7 +55,7 @@ std::unique_ptr GLGpu::createSampler(int width, int height, Pixe gl->texParameteri(sampler->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gl->texParameteri(sampler->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl->texParameteri(sampler->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - const auto& textureFormat = GLCaps::Get(_context)->getTextureFormat(format); + const auto& textureFormat = GLCaps::Get(context)->getTextureFormat(format); bool success = true; for (int level = 0; level < mipLevelCount && success; level++) { const int twoToTheMipLevel = 1 << level; @@ -57,7 +64,7 @@ std::unique_ptr GLGpu::createSampler(int width, int height, Pixe gl->texImage2D(sampler->target, level, static_cast(textureFormat.internalFormatTexImage), currentWidth, currentHeight, 0, textureFormat.externalFormat, GL_UNSIGNED_BYTE, nullptr); - success = CheckGLError(_context); + success = CheckGLError(context); } if (!success) { gl->deleteTextures(1, &(sampler->id)); @@ -71,7 +78,7 @@ void GLGpu::deleteSampler(TextureSampler* sampler) { if (glSampler == nullptr || glSampler->id == 0) { return; } - GLFunctions::Get(_context)->deleteTextures(1, &glSampler->id); + GLFunctions::Get(context)->deleteTextures(1, &glSampler->id); glSampler->id = 0; } @@ -80,12 +87,12 @@ void GLGpu::writePixels(const TextureSampler* sampler, Rect rect, const void* pi if (sampler == nullptr) { return; } - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); // https://skia-review.googlesource.com/c/skia/+/571418 // HUAWEI nova9 pro(Adreno 642L), iqoo neo5(Adreno 650), Redmi K30pro(Adreno 650), // Xiaomi 8(Adreno 630), glaxy s9(Adreno 630) gl->flush(); - auto caps = GLCaps::Get(_context); + auto caps = GLCaps::Get(context); auto glSampler = static_cast(sampler); gl->bindTexture(glSampler->target, glSampler->id); const auto& format = caps->getTextureFormat(sampler->format); @@ -173,14 +180,14 @@ void GLGpu::bindTexture(int unitIndex, const TextureSampler* sampler, SamplerSta return; } auto glSampler = static_cast(sampler); - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); gl->activeTexture(static_cast(GL_TEXTURE0 + unitIndex)); gl->bindTexture(glSampler->target, glSampler->id); gl->texParameteri(glSampler->target, GL_TEXTURE_WRAP_S, GetGLWrap(glSampler->target, samplerState.wrapModeX)); gl->texParameteri(glSampler->target, GL_TEXTURE_WRAP_T, GetGLWrap(glSampler->target, samplerState.wrapModeY)); - if (samplerState.mipMapped() && (!_context->caps()->mipMapSupport || !glSampler->hasMipmaps())) { + if (samplerState.mipMapped() && (!context->caps()->mipMapSupport || !glSampler->hasMipmaps())) { samplerState.mipMapMode = MipMapMode::None; } gl->texParameteri(glSampler->target, GL_TEXTURE_MIN_FILTER, @@ -191,7 +198,7 @@ void GLGpu::bindTexture(int unitIndex, const TextureSampler* sampler, SamplerSta void GLGpu::copyRenderTargetToTexture(const RenderTarget* renderTarget, Texture* texture, const Rect& srcRect, const Point& dstPoint) { - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); auto glRenderTarget = static_cast(renderTarget); gl->bindFramebuffer(GL_FRAMEBUFFER, glRenderTarget->getFrameBufferID(false)); auto glSampler = static_cast(texture->getSampler()); @@ -212,8 +219,8 @@ void GLGpu::resolveRenderTarget(RenderTarget* renderTarget) { if (renderTarget->sampleCount() <= 1) { return; } - auto gl = GLFunctions::Get(_context); - auto caps = GLCaps::Get(_context); + auto gl = GLFunctions::Get(context); + auto caps = GLCaps::Get(context); if (!caps->usesMSAARenderBuffers()) { return; } @@ -239,7 +246,7 @@ bool GLGpu::insertSemaphore(Semaphore* semaphore) { if (semaphore == nullptr) { return false; } - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); auto* sync = gl->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); if (sync) { static_cast(semaphore)->glSync = sync; @@ -255,28 +262,14 @@ bool GLGpu::waitSemaphore(const Semaphore* semaphore) { if (glSync == nullptr) { return false; } - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); gl->waitSync(glSync, 0, GL_TIMEOUT_IGNORED); gl->deleteSync(glSync); return true; } -RenderPass* GLGpu::getRenderPass(std::shared_ptr renderTarget, - std::shared_ptr renderTargetTexture) { - if (renderTarget == nullptr) { - return nullptr; - } - if (glRenderPass == nullptr) { - glRenderPass = GLRenderPass::Make(_context); - } - if (glRenderPass) { - glRenderPass->set(renderTarget, renderTargetTexture); - } - return glRenderPass.get(); -} - bool GLGpu::submitToGpu(bool syncCpu) { - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); if (syncCpu) { gl->finish(); } else { @@ -286,11 +279,11 @@ bool GLGpu::submitToGpu(bool syncCpu) { } void GLGpu::submit(RenderPass*) { - glRenderPass->reset(); + // does nothing for opengl. } void GLGpu::onRegenerateMipMapLevels(const TextureSampler* sampler) { - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); auto glSampler = static_cast(sampler); if (glSampler->target != GL_TEXTURE_2D) { return; diff --git a/src/opengl/GLGpu.h b/src/opengl/GLGpu.h index e993290e..4f641f9f 100644 --- a/src/opengl/GLGpu.h +++ b/src/opengl/GLGpu.h @@ -26,6 +26,8 @@ class GLGpu : public Gpu { public: static std::unique_ptr Make(Context* context); + std::shared_ptr getRenderPass() override; + std::unique_ptr createSampler(int width, int height, PixelFormat format, int mipLevelCount) override; @@ -45,19 +47,16 @@ class GLGpu : public Gpu { bool waitSemaphore(const Semaphore* semaphore) override; - RenderPass* getRenderPass(std::shared_ptr renderTarget, - std::shared_ptr renderTargetTexture) override; - bool submitToGpu(bool syncCpu) override; void submit(RenderPass* renderPass) override; private: + std::shared_ptr renderPass = nullptr; + explicit GLGpu(Context* context) : Gpu(context) { } void onRegenerateMipMapLevels(const TextureSampler* sampler) override; - - std::unique_ptr glRenderPass; }; } // namespace tgfx diff --git a/src/opengl/GLRenderPass.cpp b/src/opengl/GLRenderPass.cpp index ffbbfe3a..6d642a80 100644 --- a/src/opengl/GLRenderPass.cpp +++ b/src/opengl/GLRenderPass.cpp @@ -17,9 +17,11 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include "GLRenderPass.h" -#include "GLGpu.h" #include "GLUtil.h" +#include "gpu/DrawingManager.h" #include "gpu/ProgramCache.h" +#include "opengl/GLVertexArray.h" +#include "opengl/GLVertexArrayCreateTask.h" namespace tgfx { struct AttribLayout { @@ -43,47 +45,13 @@ static AttribLayout GetAttribLayout(SLType type) { return {false, 0, 0}; } -class VertexArrayObject : public Resource { - public: - static std::shared_ptr Make(Context* context) { - auto gl = GLFunctions::Get(context); - unsigned id = 0; - // Using VAO is required in the core profile. - gl->genVertexArrays(1, &id); - if (id == 0) { - return nullptr; - } - return Resource::AddToContext(context, new VertexArrayObject(id)); - } - - explicit VertexArrayObject(unsigned id) : id(id) { - } - - size_t memoryUsage() const override { - return 0; - } - - unsigned id = 0; - - private: - void onReleaseGPU() override { - auto gl = GLFunctions::Get(context); - if (id > 0) { - gl->deleteVertexArrays(1, &id); - id = 0; - } - } -}; - -std::unique_ptr GLRenderPass::Make(Context* context) { - std::shared_ptr vertexArrayObject; +GLRenderPass::GLRenderPass(Context* context) : RenderPass(context) { if (GLCaps::Get(context)->vertexArrayObjectSupport) { - vertexArrayObject = VertexArrayObject::Make(context); - if (vertexArrayObject == nullptr) { - return nullptr; - } + vertexArrayKey = ResourceKey::NewStrong(); + // Using VAO is required in the core profile. + auto task = std::make_shared(vertexArrayKey); + context->drawingManager()->addResourceTask(std::move(task)); } - return std::unique_ptr(new GLRenderPass(context, vertexArrayObject)); } static void UpdateScissor(Context* context, const Rect& scissorRect) { @@ -121,32 +89,21 @@ static void UpdateBlend(Context* context, const BlendInfo* blendFactors) { } } -void GLRenderPass::set(std::shared_ptr renderTarget, - std::shared_ptr renderTargetTexture) { - _renderTarget = std::move(renderTarget); - _renderTargetTexture = std::move(renderTargetTexture); -} - -void GLRenderPass::reset() { - _renderTarget = nullptr; - _renderTargetTexture = nullptr; -} - bool GLRenderPass::onBindProgramAndScissorClip(const ProgramInfo* programInfo, const Rect& drawBounds) { - _program = static_cast(_context->programCache()->getProgram(programInfo)); + _program = static_cast(context->programCache()->getProgram(programInfo)); if (_program == nullptr) { return false; } - auto gl = GLFunctions::Get(_context); - CheckGLError(_context); + auto gl = GLFunctions::Get(context); + CheckGLError(context); auto glRT = static_cast(_renderTarget.get()); auto* program = static_cast(_program); gl->useProgram(program->programID()); gl->bindFramebuffer(GL_FRAMEBUFFER, glRT->getFrameBufferID()); gl->viewport(0, 0, glRT->width(), glRT->height()); - UpdateScissor(_context, drawBounds); - UpdateBlend(_context, programInfo->blendInfo()); + UpdateScissor(context, drawBounds); + UpdateBlend(context, programInfo->blendInfo()); if (programInfo->requiresBarrier()) { gl->textureBarrier(); } @@ -164,7 +121,7 @@ static const unsigned gPrimitiveType[] = {GL_TRIANGLES, GL_TRIANGLE_STRIP}; void GLRenderPass::onDraw(PrimitiveType primitiveType, size_t baseVertex, size_t vertexCount) { auto func = [&]() { - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); gl->drawArrays(gPrimitiveType[static_cast(primitiveType)], static_cast(baseVertex), static_cast(vertexCount)); }; @@ -173,7 +130,7 @@ void GLRenderPass::onDraw(PrimitiveType primitiveType, size_t baseVertex, size_t void GLRenderPass::onDrawIndexed(PrimitiveType primitiveType, size_t baseIndex, size_t indexCount) { auto func = [&]() { - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); gl->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, std::static_pointer_cast(_indexBuffer)->bufferID()); gl->drawElements(gPrimitiveType[static_cast(primitiveType)], static_cast(indexCount), @@ -184,9 +141,10 @@ void GLRenderPass::onDrawIndexed(PrimitiveType primitiveType, size_t baseIndex, } void GLRenderPass::draw(const std::function& func) { - auto gl = GLFunctions::Get(_context); - if (vertexArrayObject) { - gl->bindVertexArray(vertexArrayObject->id); + auto gl = GLFunctions::Get(context); + auto vertexArray = Resource::Get(context, vertexArrayKey); + if (vertexArray) { + gl->bindVertexArray(vertexArray->id()); } gl->bindBuffer(GL_ARRAY_BUFFER, std::static_pointer_cast(_vertexBuffer)->bufferID()); auto* program = static_cast(_program); @@ -198,19 +156,19 @@ void GLRenderPass::draw(const std::function& func) { gl->enableVertexAttribArray(static_cast(attribute.location)); } func(); - if (vertexArrayObject) { + if (vertexArray) { gl->bindVertexArray(0); } gl->bindBuffer(GL_ARRAY_BUFFER, 0); - CheckGLError(_context); + CheckGLError(context); } void GLRenderPass::onClear(const Rect& scissor, Color color) { - auto gl = GLFunctions::Get(_context); + auto gl = GLFunctions::Get(context); auto glRT = static_cast(_renderTarget.get()); gl->bindFramebuffer(GL_FRAMEBUFFER, glRT->getFrameBufferID()); gl->viewport(0, 0, glRT->width(), glRT->height()); - UpdateScissor(_context, scissor); + UpdateScissor(context, scissor); gl->clearColor(color.red, color.green, color.blue, color.alpha); gl->clear(GL_COLOR_BUFFER_BIT); } diff --git a/src/opengl/GLRenderPass.h b/src/opengl/GLRenderPass.h index c7b9e8a1..33a0f384 100644 --- a/src/opengl/GLRenderPass.h +++ b/src/opengl/GLRenderPass.h @@ -30,16 +30,10 @@ #include "tgfx/core/BlendMode.h" namespace tgfx { -class VertexArrayObject; class GLRenderPass : public RenderPass { public: - static std::unique_ptr Make(Context* context); - - void set(std::shared_ptr renderTarget, - std::shared_ptr renderTargetTexture); - - void reset(); + explicit GLRenderPass(Context* context); protected: bool onBindProgramAndScissorClip(const ProgramInfo* programInfo, const Rect& drawBounds) override; @@ -50,12 +44,8 @@ class GLRenderPass : public RenderPass { void onClear(const Rect& scissor, Color color) override; private: - GLRenderPass(Context* context, std::shared_ptr vertexArrayObject) - : RenderPass(context), vertexArrayObject(std::move(vertexArrayObject)) { - } + ResourceKey vertexArrayKey = {}; void draw(const std::function& func); - - std::shared_ptr vertexArrayObject; }; } // namespace tgfx diff --git a/src/opengl/GLVertexArray.cpp b/src/opengl/GLVertexArray.cpp new file mode 100644 index 00000000..670b8ef1 --- /dev/null +++ b/src/opengl/GLVertexArray.cpp @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making tgfx available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "GLVertexArray.h" +#include "tgfx/opengl/GLFunctions.h" + +namespace tgfx { +std::shared_ptr GLVertexArray::Make(Context* context) { + auto gl = GLFunctions::Get(context); + unsigned id = 0; + gl->genVertexArrays(1, &id); + if (id == 0) { + return nullptr; + } + return Resource::AddToContext(context, new GLVertexArray(id)); +} + +GLVertexArray::GLVertexArray(unsigned int id) : _id(id) { +} + +void GLVertexArray::onReleaseGPU() { + auto gl = GLFunctions::Get(context); + if (_id > 0) { + gl->deleteVertexArrays(1, &_id); + _id = 0; + } +} +} // namespace tgfx diff --git a/src/opengl/GLVertexArray.h b/src/opengl/GLVertexArray.h new file mode 100644 index 00000000..d0945166 --- /dev/null +++ b/src/opengl/GLVertexArray.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making tgfx available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "gpu/Resource.h" + +namespace tgfx { +class GLVertexArray : public Resource { + public: + static std::shared_ptr Make(Context* context); + + explicit GLVertexArray(unsigned id); + + size_t memoryUsage() const override { + return 0; + } + + unsigned id() const { + return _id; + } + + private: + unsigned _id = 0; + + void onReleaseGPU() override; +}; +} // namespace tgfx diff --git a/src/opengl/GLVertexArrayCreateTask.cpp b/src/opengl/GLVertexArrayCreateTask.cpp new file mode 100644 index 00000000..d1ad1f93 --- /dev/null +++ b/src/opengl/GLVertexArrayCreateTask.cpp @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making tgfx available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "GLVertexArrayCreateTask.h" +#include "GLVertexArray.h" + +namespace tgfx { +GLVertexArrayCreateTask::GLVertexArrayCreateTask(ResourceKey strongKey) + : ResourceTask(std::move(strongKey)) { +} + +std::shared_ptr GLVertexArrayCreateTask::onMakeResource(Context* context) { + auto vertexArray = GLVertexArray::Make(context); + if (vertexArray == nullptr) { + LOGE("GLVertexArrayCreateTask::onMakeResource() Failed to create the vertex array!"); + } + return vertexArray; +} +} // namespace tgfx diff --git a/src/opengl/GLVertexArrayCreateTask.h b/src/opengl/GLVertexArrayCreateTask.h new file mode 100644 index 00000000..5bc7fdd7 --- /dev/null +++ b/src/opengl/GLVertexArrayCreateTask.h @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making tgfx available. +// +// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// unless required by applicable law or agreed to in writing, software distributed under the +// license is distributed on an "as is" basis, without warranties or conditions of any kind, +// either express or implied. see the license for the specific language governing permissions +// and limitations under the license. +// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "gpu/tasks/ResourceTask.h" + +namespace tgfx { +class GLVertexArrayCreateTask : public ResourceTask { + public: + explicit GLVertexArrayCreateTask(ResourceKey strongKey); + + std::shared_ptr onMakeResource(Context* context) override; +}; +} // namespace tgfx