diff --git a/src/base/utils/TGFXCast.cpp b/src/base/utils/TGFXCast.cpp index 28ad7a3050..e9bfeeb90b 100644 --- a/src/base/utils/TGFXCast.cpp +++ b/src/base/utils/TGFXCast.cpp @@ -141,4 +141,38 @@ ColorType ToPAG(tgfx::ColorType colorType) { return ColorType::Unknown; } } + +tgfx::GLSemaphore ToTGFX(const BackendSemaphore& semaphore) { + tgfx::GLSemaphore glSemaphore = {}; + glSemaphore.glSync = semaphore.glSync(); + return glSemaphore; +} + +bool GetGLSampler(const BackendTexture& texture, tgfx::GLSampler* sampler) { + GLTextureInfo glInfo = {}; + if (!texture.getGLTextureInfo(&glInfo)) { + return false; + } + sampler->id = glInfo.id; + sampler->target = glInfo.target; + sampler->format = tgfx::PixelFormat::RGBA_8888; + return true; +} + +bool GetGLFrameBuffer(const BackendRenderTarget& renderTarget, tgfx::GLFrameBuffer* frameBuffer) { + GLFrameBufferInfo glInfo = {}; + if (!renderTarget.getGLFramebufferInfo(&glInfo)) { + return false; + } + frameBuffer->id = glInfo.id; + frameBuffer->format = tgfx::PixelFormat::RGBA_8888; + return true; +} + +BackendTexture ToBackendTexture(const tgfx::GLSampler& sampler, int width, int height) { + GLTextureInfo glInfo = {}; + glInfo.id = sampler.id; + glInfo.target = sampler.target; + return BackendTexture(glInfo, width, height); +} } // namespace pag diff --git a/src/base/utils/TGFXCast.h b/src/base/utils/TGFXCast.h index 0ec25de4a5..3ccfc55c26 100644 --- a/src/base/utils/TGFXCast.h +++ b/src/base/utils/TGFXCast.h @@ -25,6 +25,9 @@ #include "core/Matrix.h" #include "core/Stroke.h" #include "gpu/Backend.h" +#include "gpu/opengl/GLFrameBuffer.h" +#include "gpu/opengl/GLSampler.h" +#include "gpu/opengl/GLSemaphore.h" #include "pag/file.h" #include "pag/gpu.h" @@ -52,29 +55,13 @@ tgfx::ColorType ToTGFX(ColorType colorType); ColorType ToPAG(tgfx::ColorType colorType); -static inline tgfx::BackendTexture ToTGFX(const BackendTexture& texture) { - return *reinterpret_cast(&texture); -} - -static inline BackendTexture ToPAG(const tgfx::BackendTexture& texture) { - return *reinterpret_cast(&texture); -} - -static inline tgfx::BackendRenderTarget ToTGFX(const BackendRenderTarget& renderTarget) { - return *reinterpret_cast(&renderTarget); -} +bool GetGLSampler(const BackendTexture& texture, tgfx::GLSampler* sampler); -static inline BackendRenderTarget ToPAG(const tgfx::BackendRenderTarget& renderTarget) { - return *reinterpret_cast(&renderTarget); -} +bool GetGLFrameBuffer(const BackendRenderTarget& renderTarget, tgfx::GLFrameBuffer* frameBuffer); -static inline tgfx::BackendSemaphore* ToTGFX(BackendSemaphore* semaphore) { - return reinterpret_cast(semaphore); -} +BackendTexture ToBackendTexture(const tgfx::GLSampler& sampler, int width, int height); -static inline tgfx::BackendSemaphore ToTGFX(const BackendSemaphore& semaphore) { - return *reinterpret_cast(&semaphore); -} +tgfx::GLSemaphore ToTGFX(const BackendSemaphore& semaphore); static inline const tgfx::Matrix* ToTGFX(const Matrix* matrix) { return reinterpret_cast(matrix); diff --git a/src/platform/android/GPUDecoder.cpp b/src/platform/android/GPUDecoder.cpp index a51ef03165..55391bba54 100644 --- a/src/platform/android/GPUDecoder.cpp +++ b/src/platform/android/GPUDecoder.cpp @@ -66,7 +66,7 @@ GPUDecoder::GPUDecoder(const VideoConfig& config) { if (env == nullptr) { return; } - videoSurface = VideoSurface::Make(config.width, config.height, config.hasAlpha); + videoSurface = VideoSurface::Make(config.width, config.height); if (videoSurface == nullptr) { return; } @@ -192,11 +192,12 @@ std::shared_ptr GPUDecoder::onRenderFrame() { if (env == nullptr) { return nullptr; } - videoSurface->updateTexImage(); + videoSurface->clearPendingTexImage(); auto result = env->CallBooleanMethod(videoDecoder.get(), GPUDecoder_onRenderFrame); if (!result) { return nullptr; } + videoSurface->markPendingTexImage(); return VideoImage::MakeFrom(videoSurface, videoWidth, videoHeight); } } // namespace pag \ No newline at end of file diff --git a/src/platform/android/JPAGSurface.cpp b/src/platform/android/JPAGSurface.cpp index e23c9125ca..31d34804dc 100644 --- a/src/platform/android/JPAGSurface.cpp +++ b/src/platform/android/JPAGSurface.cpp @@ -17,6 +17,9 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include "JPAGSurface.h" +#include +#include +#include #include #include "GPUDecoder.h" #include "GPUDrawable.h" @@ -130,9 +133,9 @@ JNIEXPORT jlong Java_org_libpag_PAGSurface_SetupFromTexture(JNIEnv*, jclass, jin jint width, jint height, jboolean flipY, jboolean forAsyncThread) { GLTextureInfo glInfo = {}; - glInfo.target = GL::TEXTURE_2D; + glInfo.target = GL_TEXTURE_2D; glInfo.id = static_cast(textureID); - glInfo.format = GL::RGBA8; + glInfo.format = GL_RGBA8; BackendTexture glTexture(glInfo, width, height); auto origin = flipY ? ImageOrigin::BottomLeft : ImageOrigin::TopLeft; diff --git a/src/platform/android/VideoImage.cpp b/src/platform/android/VideoImage.cpp index 743a3c1c8b..d3d728e1c3 100644 --- a/src/platform/android/VideoImage.cpp +++ b/src/platform/android/VideoImage.cpp @@ -31,17 +31,10 @@ std::shared_ptr VideoImage::MakeFrom(std::shared_ptr v VideoImage::VideoImage(std::shared_ptr videoSurface, int width, int height) : VideoBuffer(width, height), videoSurface(std::move(videoSurface)) { - this->videoSurface->markHasNewTextureImage(); } std::shared_ptr VideoImage::makeTexture(tgfx::Context* context) const { std::lock_guard autoLock(locker); - if (!videoSurface->attachToContext(context)) { - return nullptr; - } - if (!videoSurface->updateTexImage()) { - return nullptr; - } - return videoSurface->getTexture(); + return videoSurface->makeTexture(context); } } // namespace pag diff --git a/src/platform/android/VideoSurface.cpp b/src/platform/android/VideoSurface.cpp index 86312c263f..311cc96268 100644 --- a/src/platform/android/VideoSurface.cpp +++ b/src/platform/android/VideoSurface.cpp @@ -18,6 +18,7 @@ #include "VideoSurface.h" #include "android/native_window_jni.h" +#include "gpu/opengl/GLContext.h" #include "gpu/opengl/GLTexture.h" namespace pag { @@ -44,10 +45,9 @@ void VideoSurface::InitJNI(JNIEnv* env, const std::string& className) { VideoSurface_onRelease = env->GetMethodID(VideoSurfaceClass.get(), "onRelease", "()V"); } -OESTexture::OESTexture(tgfx::GLTextureInfo info, int width, int height, bool hasAlpha) - : GLTexture(width, height, tgfx::ImageOrigin::TopLeft), hasAlpha(hasAlpha) { - sampler.glInfo = info; - sampler.config = tgfx::PixelConfig::RGBA_8888; +OESTexture::OESTexture(const tgfx::GLSampler& glSampler, int width, int height) + : GLTexture(width, height, tgfx::ImageOrigin::TopLeft) { + sampler = glSampler; } void OESTexture::setTextureSize(int width, int height) { @@ -57,7 +57,7 @@ void OESTexture::setTextureSize(int width, int height) { } void OESTexture::computeTransform() { - if (textureWidth == 0 || textureHeight == 0 || hasAlpha) { + if (textureWidth == 0 || textureHeight == 0) { return; } // https://cs.android.com/android/platform/superproject/+/master:frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp;l=275;drc=master;bpv=0;bpt=1 @@ -81,21 +81,17 @@ void OESTexture::computeTransform() { } tgfx::Point OESTexture::getTextureCoord(float x, float y) const { - if (hasAlpha) { - // 如果有 alpha 通道,不需要缩小纹素 - return {x / static_cast(textureWidth), y / static_cast(textureHeight)}; - } return {x / static_cast(width()) * sx + tx, y / static_cast(height()) * sy + ty}; } void OESTexture::onRelease(tgfx::Context* context) { - if (sampler.glInfo.id > 0) { + if (sampler.id > 0) { auto gl = tgfx::GLContext::Unwrap(context); - gl->deleteTextures(1, &sampler.glInfo.id); + gl->deleteTextures(1, &sampler.id); } } -std::shared_ptr VideoSurface::Make(int width, int height, bool hasAlpha) { +std::shared_ptr VideoSurface::Make(int width, int height) { auto env = JNIEnvironment::Current(); if (env == nullptr) { return nullptr; @@ -105,12 +101,11 @@ std::shared_ptr VideoSurface::Make(int width, int height, bool has if (surface.empty()) { return nullptr; } - return std::shared_ptr( - new VideoSurface(env, surface.get(), width, height, hasAlpha)); + return std::shared_ptr(new VideoSurface(env, surface.get(), width, height)); } -VideoSurface::VideoSurface(JNIEnv* env, jobject surface, int width, int height, bool hasAlpha) - : width(width), height(height), hasAlpha(hasAlpha) { +VideoSurface::VideoSurface(JNIEnv* env, jobject surface, int width, int height) + : width(width), height(height) { videoSurface.reset(env, surface); } @@ -126,8 +121,41 @@ jobject VideoSurface::getOutputSurface(JNIEnv* env) const { return env->CallObjectMethod(videoSurface.get(), VideoSurface_getOutputSurface); } -bool VideoSurface::attachToContext(tgfx::Context* context) { - if (oesTexture) { +void VideoSurface::markPendingTexImage() { + hasPendingTextureImage = true; +} + +void VideoSurface::clearPendingTexImage() { + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return; + } + updateTexImage(env); +} + +std::shared_ptr VideoSurface::makeTexture(tgfx::Context* context) { + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return nullptr; + } + if (!attachToContext(env, context)) { + return nullptr; + } + if (!updateTexImage(env)) { + return nullptr; + } + if (oesTexture == nullptr) { + auto textureWidth = env->CallIntMethod(videoSurface.get(), VideoSurface_videoWidth); + auto textureHeight = env->CallIntMethod(videoSurface.get(), VideoSurface_videoHeight); + oesTexture = tgfx::Resource::Wrap(context, new OESTexture(glInfo, width, height)); + oesTexture->setTextureSize(textureWidth, textureHeight); + oesTexture->attachedSurface.reset(env, videoSurface.get()); + } + return oesTexture; +} + +bool VideoSurface::attachToContext(JNIEnv* env, tgfx::Context* context) { + if (glInfo.id > 0) { if (deviceID != context->device()->uniqueID()) { LOGE("VideoSurface::attachToGLContext(): VideoSurface has already attached to a Context!"); return false; @@ -135,59 +163,32 @@ bool VideoSurface::attachToContext(tgfx::Context* context) { return true; } auto gl = tgfx::GLContext::Unwrap(context); - tgfx::GLTextureInfo glInfo = {}; - glInfo.target = GL::TEXTURE_EXTERNAL_OES; - glInfo.format = GL::RGBA8; - gl->genTextures(1, &glInfo.id); - oesTexture = tgfx::Resource::Wrap(context, new OESTexture(glInfo, width, height, hasAlpha)); - auto env = JNIEnvironment::Current(); - if (env == nullptr) { + tgfx::GLSampler sampler = {}; + sampler.target = GL::TEXTURE_EXTERNAL_OES; + sampler.format = tgfx::PixelFormat::RGBA_8888; + gl->genTextures(1, &sampler.id); + if (sampler.id == 0) { return false; } - auto result = env->CallBooleanMethod(videoSurface.get(), VideoSurface_attachToGLContext, - oesTexture->getGLInfo().id); - deviceID = context->device()->uniqueID(); + auto result = + env->CallBooleanMethod(videoSurface.get(), VideoSurface_attachToGLContext, sampler.id); if (!result) { + gl->deleteTextures(1, &sampler.id); LOGE("VideoSurface::attachToGLContext(): failed to attached to a Surface!"); - oesTexture = nullptr; - deviceID = 0; return false; } - oesTexture->attachedSurface.reset(env, videoSurface.get()); + glInfo = sampler; + deviceID = context->device()->uniqueID(); return true; } -void VideoSurface::markHasNewTextureImage() { - hasPendingTextureImage = true; -} - -bool VideoSurface::updateTexImage() { +bool VideoSurface::updateTexImage(JNIEnv* env) { if (!hasPendingTextureImage) { return false; } - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return false; - } - bool status = env->CallBooleanMethod(videoSurface.get(), VideoSurface_updateTexImage); + auto result = env->CallBooleanMethod(videoSurface.get(), VideoSurface_updateTexImage); hasPendingTextureImage = false; - return status; + return result; } -std::shared_ptr VideoSurface::getTexture() { - if (oesTexture == nullptr) { - return nullptr; - } - if (oesTexture->textureWidth > 0) { - return oesTexture; - } - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return nullptr; - } - auto textureWidth = env->CallIntMethod(videoSurface.get(), VideoSurface_videoWidth); - auto textureHeight = env->CallIntMethod(videoSurface.get(), VideoSurface_videoHeight); - oesTexture->setTextureSize(textureWidth, textureHeight); - return oesTexture; -} } // namespace pag diff --git a/src/platform/android/VideoSurface.h b/src/platform/android/VideoSurface.h index f3eeec80f6..ba57c88795 100644 --- a/src/platform/android/VideoSurface.h +++ b/src/platform/android/VideoSurface.h @@ -24,7 +24,7 @@ namespace pag { class OESTexture : public tgfx::GLTexture { public: - OESTexture(tgfx::GLTextureInfo info, int width, int height, bool hasAlpha); + OESTexture(const tgfx::GLSampler& sampler, int width, int height); tgfx::Point getTextureCoord(float x, float y) const override; @@ -42,7 +42,6 @@ class OESTexture : public tgfx::GLTexture { int textureWidth = 0; int textureHeight = 0; - bool hasAlpha = false; // 持有 Java 的 Surface,确保即使 GPUDecoder 提前释放也能正常被使用。 Global attachedSurface; float sx = 1.0f; @@ -57,29 +56,29 @@ class VideoSurface { public: static void InitJNI(JNIEnv* env, const std::string& className); - static std::shared_ptr Make(int width, int height, bool hasAlpha = false); + static std::shared_ptr Make(int width, int height); ~VideoSurface(); jobject getOutputSurface(JNIEnv* env) const; - bool attachToContext(tgfx::Context* context); + void markPendingTexImage(); - bool updateTexImage(); + void clearPendingTexImage(); - std::shared_ptr getTexture(); - - void markHasNewTextureImage(); + std::shared_ptr makeTexture(tgfx::Context* context); private: Global videoSurface; int width = 0; int height = 0; - bool hasAlpha = false; uint32_t deviceID = 0; + tgfx::GLSampler glInfo = {}; std::shared_ptr oesTexture = nullptr; mutable std::atomic_bool hasPendingTextureImage = {false}; - VideoSurface(JNIEnv* env, jobject surface, int width, int height, bool hasAlpha); + VideoSurface(JNIEnv* env, jobject surface, int width, int height); + bool attachToContext(JNIEnv* env, tgfx::Context* context); + bool updateTexImage(JNIEnv* env); }; } // namespace pag diff --git a/src/rendering/Drawable.cpp b/src/rendering/Drawable.cpp index 0b899de9d0..bc66f0a8dd 100644 --- a/src/rendering/Drawable.cpp +++ b/src/rendering/Drawable.cpp @@ -18,25 +18,38 @@ #include "Drawable.h" #include "base/utils/TGFXCast.h" +#include "gpu/opengl/GLRenderTarget.h" namespace pag { RenderTargetDrawable::RenderTargetDrawable(std::shared_ptr device, - const tgfx::BackendRenderTarget& renderTarget, + const BackendRenderTarget& renderTarget, tgfx::ImageOrigin origin) : device(std::move(device)), renderTarget(renderTarget), origin(origin) { } std::shared_ptr RenderTargetDrawable::createSurface(tgfx::Context* context) { - return tgfx::Surface::MakeFrom(context, renderTarget, origin); + tgfx::GLFrameBuffer frameBuffer = {}; + if (!GetGLFrameBuffer(renderTarget, &frameBuffer)) { + return nullptr; + } + auto glRT = tgfx::GLRenderTarget::MakeFrom(context, frameBuffer, renderTarget.width(), + renderTarget.height(), origin); + return tgfx::Surface::MakeFrom(context, std::move(glRT)); } TextureDrawable::TextureDrawable(std::shared_ptr device, - const tgfx::BackendTexture& texture, tgfx::ImageOrigin origin) + const BackendTexture& texture, tgfx::ImageOrigin origin) : device(std::move(device)), texture(texture), origin(origin) { } std::shared_ptr TextureDrawable::createSurface(tgfx::Context* context) { - return tgfx::Surface::MakeFrom(context, texture, origin); + tgfx::GLSampler sampler = {}; + if (!GetGLSampler(texture, &sampler)) { + return nullptr; + } + auto glTexture = + tgfx::GLTexture::MakeFrom(context, sampler, texture.width(), texture.height(), origin); + return tgfx::Surface::MakeFrom(context, std::move(glTexture)); } OffscreenDrawable::OffscreenDrawable(int width, int height, std::shared_ptr device) diff --git a/src/rendering/Drawable.h b/src/rendering/Drawable.h index b29bd5ffeb..4259d3e9e1 100644 --- a/src/rendering/Drawable.h +++ b/src/rendering/Drawable.h @@ -25,7 +25,7 @@ namespace pag { class RenderTargetDrawable : public Drawable { public: RenderTargetDrawable(std::shared_ptr device, - const tgfx::BackendRenderTarget& renderTarget, tgfx::ImageOrigin origin); + const BackendRenderTarget& renderTarget, tgfx::ImageOrigin origin); int width() const override { return renderTarget.width(); @@ -49,13 +49,13 @@ class RenderTargetDrawable : public Drawable { private: std::shared_ptr device = nullptr; - tgfx::BackendRenderTarget renderTarget = {}; + BackendRenderTarget renderTarget = {}; tgfx::ImageOrigin origin = tgfx::ImageOrigin::TopLeft; }; class TextureDrawable : public Drawable { public: - TextureDrawable(std::shared_ptr device, const tgfx::BackendTexture& texture, + TextureDrawable(std::shared_ptr device, const BackendTexture& texture, tgfx::ImageOrigin origin); int width() const override { @@ -80,7 +80,7 @@ class TextureDrawable : public Drawable { private: std::shared_ptr device = nullptr; - tgfx::BackendTexture texture = {}; + BackendTexture texture = {}; tgfx::ImageOrigin origin = tgfx::ImageOrigin::TopLeft; }; diff --git a/src/rendering/GPUBackend.cpp b/src/rendering/GPUBackend.cpp index 31fa2f3675..f1b241dfb7 100644 --- a/src/rendering/GPUBackend.cpp +++ b/src/rendering/GPUBackend.cpp @@ -122,6 +122,9 @@ BackendSemaphore::BackendSemaphore() } void BackendSemaphore::initGL(void* sync) { + if (sync == nullptr) { + return; + } _backend = Backend::OPENGL; _glSync = sync; _isInitialized = true; diff --git a/src/rendering/PAGSurface.cpp b/src/rendering/PAGSurface.cpp index f8a26e9c75..91257c9a51 100644 --- a/src/rendering/PAGSurface.cpp +++ b/src/rendering/PAGSurface.cpp @@ -53,8 +53,7 @@ std::shared_ptr PAGSurface::MakeFrom(const BackendRenderTarget& rend if (device == nullptr || !renderTarget.isValid()) { return nullptr; } - auto drawable = - std::make_shared(device, ToTGFX(renderTarget), ToTGFX(origin)); + auto drawable = std::make_shared(device, renderTarget, ToTGFX(origin)); return MakeFrom(std::move(drawable)); } @@ -64,7 +63,7 @@ std::shared_ptr PAGSurface::MakeFrom(const BackendTexture& texture, if (device == nullptr || !texture.isValid()) { return nullptr; } - auto drawable = std::make_shared(device, ToTGFX(texture), ToTGFX(origin)); + auto drawable = std::make_shared(device, texture, ToTGFX(origin)); return MakeFrom(std::move(drawable)); } @@ -183,7 +182,13 @@ bool PAGSurface::draw(RenderCache* cache, std::shared_ptr graphic, if (graphic) { graphic->draw(canvas, cache); } - surface->flush(ToTGFX(signalSemaphore)); + if (signalSemaphore == nullptr) { + surface->flush(); + } else { + tgfx::GLSemaphore semaphore = {}; + surface->flush(&semaphore); + signalSemaphore->initGL(semaphore.glSync); + } cache->detachFromContext(); drawable->setTimeStamp(pagPlayer->getTimeStampInternal()); drawable->present(context); @@ -209,7 +214,8 @@ bool PAGSurface::wait(const BackendSemaphore& waitSemaphore) { unlockContext(); return false; } - auto ret = surface->wait(ToTGFX(waitSemaphore)); + auto semaphore = ToTGFX(waitSemaphore); + auto ret = surface->wait(&semaphore); unlockContext(); return ret; } diff --git a/src/rendering/editing/StillImage.cpp b/src/rendering/editing/StillImage.cpp index 8cfd408e67..d52dd6403f 100644 --- a/src/rendering/editing/StillImage.cpp +++ b/src/rendering/editing/StillImage.cpp @@ -102,7 +102,7 @@ std::shared_ptr PAGImage::FromTexture(const BackendTexture& texture, I return nullptr; } auto pagImage = std::make_shared(); - auto picture = Picture::MakeFrom(pagImage->uniqueID(), ToTGFX(texture), ToTGFX(origin)); + auto picture = Picture::MakeFrom(pagImage->uniqueID(), texture, ToTGFX(origin)); if (!picture) { LOGE("PAGImage.MakeFrom() The texture is invalid."); return nullptr; diff --git a/src/rendering/filters/DisplacementMapFilter.cpp b/src/rendering/filters/DisplacementMapFilter.cpp index 18264557f0..f66ebf7bbe 100644 --- a/src/rendering/filters/DisplacementMapFilter.cpp +++ b/src/rendering/filters/DisplacementMapFilter.cpp @@ -120,8 +120,8 @@ void DisplacementMapFilter::updateMapTexture(RenderCache* cache, const Graphic* void DisplacementMapFilter::onUpdateParams(const tgfx::GLInterface* gl, const tgfx::Rect& contentBounds, const tgfx::Point&) { auto* pagEffect = reinterpret_cast(effect); - auto mapTexture = tgfx::GLTexture::Unwrap(mapSurface->getTexture().get()); - ActiveGLTexture(gl, GL::TEXTURE1, GL::TEXTURE_2D, mapTexture.id); + auto mapTextureID = GetTextureID(mapSurface->getTexture().get()); + ActiveGLTexture(gl, GL::TEXTURE1, GL::TEXTURE_2D, mapTextureID); gl->uniform2f(useForDisplacementHandle, pagEffect->useForHorizontalDisplacement->getValueAt(layerFrame), pagEffect->useForVerticalDisplacement->getValueAt(layerFrame)); diff --git a/src/rendering/filters/utils/FilterBuffer.cpp b/src/rendering/filters/utils/FilterBuffer.cpp index f3fc1fd601..a4131ad924 100644 --- a/src/rendering/filters/utils/FilterBuffer.cpp +++ b/src/rendering/filters/utils/FilterBuffer.cpp @@ -21,36 +21,39 @@ namespace pag { std::shared_ptr FilterBuffer::Make(tgfx::Context* context, int width, int height, bool usesMSAA) { - auto texture = tgfx::GLTexture::MakeRGBA(context, width, height); - auto gl = tgfx::GLContext::Unwrap(context); - auto sampleCount = usesMSAA ? gl->caps->getSampleCount(4, tgfx::PixelConfig::RGBA_8888) : 1; - auto renderTarget = tgfx::GLRenderTarget::MakeFrom(context, texture.get(), sampleCount); - if (renderTarget == nullptr) { + auto sampleCount = usesMSAA ? 4 : 1; + auto surface = tgfx::Surface::Make(context, width, height, false, sampleCount); + if (surface == nullptr) { return nullptr; } auto buffer = new FilterBuffer(); - buffer->texture = texture; - buffer->renderTarget = renderTarget; + buffer->surface = surface; return std::shared_ptr(buffer); } -void FilterBuffer::resolve(tgfx::Context* context) { - renderTarget->resolve(context); +tgfx::GLFrameBuffer FilterBuffer::getFramebuffer() const { + auto renderTarget = std::static_pointer_cast(surface->getRenderTarget()); + return renderTarget->glFrameBuffer(); } -void FilterBuffer::clearColor(const tgfx::GLInterface* gl) const { - renderTarget->clear(gl); +tgfx::GLSampler FilterBuffer::getTexture() const { + auto texture = std::static_pointer_cast(surface->getTexture()); + return texture->glSampler(); +} + +void FilterBuffer::clearColor(const tgfx::GLInterface*) const { + surface->getCanvas()->clear(); } std::unique_ptr FilterBuffer::toFilterSource(const tgfx::Point& scale) const { auto filterSource = new FilterSource(); filterSource->textureID = getTexture().id; - filterSource->width = texture->width(); - filterSource->height = texture->height(); + filterSource->width = surface->width(); + filterSource->height = surface->height(); filterSource->scale = scale; // TODO(domrjchen): 这里的 ImageOrigin 是错的 filterSource->textureMatrix = tgfx::ToGLTextureMatrix( - tgfx::Matrix::I(), texture->width(), texture->height(), tgfx::ImageOrigin::BottomLeft); + tgfx::Matrix::I(), surface->width(), surface->height(), tgfx::ImageOrigin::BottomLeft); return std::unique_ptr(filterSource); } @@ -58,10 +61,10 @@ std::unique_ptr FilterBuffer::toFilterTarget( const tgfx::Matrix& drawingMatrix) const { auto filterTarget = new FilterTarget(); filterTarget->frameBufferID = getFramebuffer().id; - filterTarget->width = renderTarget->width(); - filterTarget->height = renderTarget->height(); + filterTarget->width = surface->width(); + filterTarget->height = surface->height(); filterTarget->vertexMatrix = tgfx::ToGLVertexMatrix( - drawingMatrix, renderTarget->width(), renderTarget->height(), tgfx::ImageOrigin::BottomLeft); + drawingMatrix, surface->width(), surface->height(), tgfx::ImageOrigin::BottomLeft); return std::unique_ptr(filterTarget); } } // namespace pag diff --git a/src/rendering/filters/utils/FilterBuffer.h b/src/rendering/filters/utils/FilterBuffer.h index c5b8aaa027..682973b48b 100644 --- a/src/rendering/filters/utils/FilterBuffer.h +++ b/src/rendering/filters/utils/FilterBuffer.h @@ -18,6 +18,7 @@ #pragma once +#include "gpu/Surface.h" #include "gpu/opengl/GLRenderTarget.h" #include "gpu/opengl/GLUtil.h" #include "pag/file.h" @@ -37,30 +38,24 @@ class FilterBuffer { std::unique_ptr toFilterTarget(const tgfx::Matrix& drawingMatrix) const; int width() const { - return renderTarget->width(); + return surface->width(); } int height() const { - return renderTarget->height(); + return surface->height(); } bool usesMSAA() const { - return renderTarget->usesMSAA(); + return surface->getRenderTarget()->sampleCount() > 1; } - tgfx::GLFrameBufferInfo getFramebuffer() const { - return renderTarget->getGLInfo(); - } - - tgfx::GLTextureInfo getTexture() const { - return texture->getGLInfo(); - } + tgfx::GLFrameBuffer getFramebuffer() const; - void resolve(tgfx::Context* context); + tgfx::GLSampler getTexture() const; private: - std::shared_ptr renderTarget = nullptr; - std::shared_ptr texture = nullptr; + std::shared_ptr surface = nullptr; + FilterBuffer() = default; }; } // namespace pag diff --git a/src/rendering/filters/utils/FilterHelper.cpp b/src/rendering/filters/utils/FilterHelper.cpp index 352bd2f7b9..c66c093a42 100644 --- a/src/rendering/filters/utils/FilterHelper.cpp +++ b/src/rendering/filters/utils/FilterHelper.cpp @@ -48,9 +48,8 @@ std::unique_ptr ToFilterSource(const tgfx::Texture* texture, if (texture == nullptr) { return nullptr; } - auto textureInfo = tgfx::GLTexture::Unwrap(texture); auto filterSource = new FilterSource(); - filterSource->textureID = textureInfo.id; + filterSource->textureID = GetTextureID(texture); filterSource->width = texture->width(); filterSource->height = texture->height(); filterSource->scale = scale; @@ -64,9 +63,9 @@ std::unique_ptr ToFilterTarget(const tgfx::Surface* surface, if (surface == nullptr) { return nullptr; } - auto renderTarget = static_cast(surface)->getRenderTarget(); + auto renderTarget = std::static_pointer_cast(surface->getRenderTarget()); auto filterTarget = new FilterTarget(); - filterTarget->frameBufferID = renderTarget->getGLInfo().id; + filterTarget->frameBufferID = renderTarget->glFrameBuffer().id; filterTarget->width = surface->width(); filterTarget->height = surface->height(); filterTarget->vertexMatrix = @@ -94,4 +93,11 @@ void PreConcatMatrix(FilterTarget* target, const tgfx::Matrix& matrix) { target->vertexMatrix = tgfx::ToGLVertexMatrix(vertexMatrix, target->width, target->height, tgfx::ImageOrigin::BottomLeft); } + +unsigned GetTextureID(const tgfx::Texture* texture) { + if (texture == nullptr || texture->isYUV()) { + return 0; + } + return static_cast(texture)->glSampler().id; +} } // namespace pag diff --git a/src/rendering/filters/utils/FilterHelper.h b/src/rendering/filters/utils/FilterHelper.h index 6dbf4aee6a..b64905dcd4 100644 --- a/src/rendering/filters/utils/FilterHelper.h +++ b/src/rendering/filters/utils/FilterHelper.h @@ -40,4 +40,6 @@ tgfx::Point ToGLVertexPoint(const FilterTarget* target, const FilterSource* sour const tgfx::Rect& contentBounds, const tgfx::Point& contentPoint); void PreConcatMatrix(FilterTarget* target, const tgfx::Matrix& matrix); + +unsigned GetTextureID(const tgfx::Texture* texture); } // namespace pag diff --git a/src/rendering/graphics/Picture.cpp b/src/rendering/graphics/Picture.cpp index 9e0d208b60..1001b95b08 100644 --- a/src/rendering/graphics/Picture.cpp +++ b/src/rendering/graphics/Picture.cpp @@ -21,6 +21,7 @@ #include "base/utils/MatrixUtil.h" #include "gpu/Surface.h" #include "gpu/opengl/GLDevice.h" +#include "gpu/opengl/GLTexture.h" #include "rendering/caches/RenderCache.h" namespace pag { @@ -407,8 +408,7 @@ class ImageTextureProxy : public TextureProxy { class BackendTextureProxy : public TextureProxy { public: - BackendTextureProxy(const tgfx::BackendTexture& texture, tgfx::ImageOrigin origin, - void* sharedContext) + BackendTextureProxy(const BackendTexture& texture, tgfx::ImageOrigin origin, void* sharedContext) : TextureProxy(texture.width(), texture.height()), backendTexture(texture), origin(origin), sharedContext(sharedContext) { } @@ -425,11 +425,16 @@ class BackendTextureProxy : public TextureProxy { if (!checkContext(context)) { return nullptr; } - return tgfx::Texture::MakeFrom(context, backendTexture, origin); + tgfx::GLSampler sampler = {}; + if (!GetGLSampler(backendTexture, &sampler)) { + return nullptr; + } + return tgfx::GLTexture::MakeFrom(context, sampler, backendTexture.width(), + backendTexture.height(), origin); } private: - tgfx::BackendTexture backendTexture = {}; + BackendTexture backendTexture = {}; tgfx::ImageOrigin origin = tgfx::ImageOrigin::TopLeft; void* sharedContext = nullptr; @@ -474,7 +479,7 @@ std::shared_ptr Picture::MakeFrom(ID assetID, return std::shared_ptr(new TextureProxyPicture(assetID, proxy, false)); } -std::shared_ptr Picture::MakeFrom(ID assetID, const tgfx::BackendTexture& texture, +std::shared_ptr Picture::MakeFrom(ID assetID, const BackendTexture& texture, tgfx::ImageOrigin origin) { if (!texture.isValid()) { return nullptr; diff --git a/src/rendering/graphics/Picture.h b/src/rendering/graphics/Picture.h index 48e1b9663d..b8ac997b3e 100644 --- a/src/rendering/graphics/Picture.h +++ b/src/rendering/graphics/Picture.h @@ -22,6 +22,7 @@ #include "core/Bitmap.h" #include "core/Image.h" #include "core/RGBAAALayout.h" +#include "pag/gpu.h" #include "rendering/graphics/Snapshot.h" namespace pag { @@ -47,7 +48,7 @@ class Picture : public Graphic { /** * Creates a new Picture with specified backend texture. Returns null if the texture is invalid. */ - static std::shared_ptr MakeFrom(ID assetID, const tgfx::BackendTexture& texture, + static std::shared_ptr MakeFrom(ID assetID, const BackendTexture& texture, tgfx::ImageOrigin origin); /* diff --git a/src/rendering/renderers/FilterRenderer.cpp b/src/rendering/renderers/FilterRenderer.cpp index ef0df63f82..5ae5d5b58f 100644 --- a/src/rendering/renderers/FilterRenderer.cpp +++ b/src/rendering/renderers/FilterRenderer.cpp @@ -341,7 +341,6 @@ void ApplyFilters(tgfx::Context* context, std::vector filterNodes, (lastBounds.top - node.bounds.top) * scale.y); auto currentTarget = currentBuffer->toFilterTarget(offsetMatrix); node.filter->draw(context, source, currentTarget.get()); - currentBuffer->resolve(context); lastSource = currentBuffer->toFilterSource(scale); freeBuffer = lastBuffer; lastBuffer = currentBuffer; diff --git a/test/GLUtilTest.cpp b/test/GLUtilTest.cpp index b8ea453a56..f4e48b64d7 100644 --- a/test/GLUtilTest.cpp +++ b/test/GLUtilTest.cpp @@ -119,10 +119,10 @@ PAG_TEST_F(GLUtilTest, Caps_ID82991749) { EXPECT_EQ(caps.standard, GLStandard::GL); EXPECT_TRUE(caps.textureRedSupport); EXPECT_TRUE(caps.multisampleDisableSupport); - EXPECT_EQ(caps.getSampleCount(5, PixelConfig::RGBA_8888), 8); - EXPECT_EQ(caps.getSampleCount(10, PixelConfig::RGBA_8888), 1); - EXPECT_EQ(caps.getSampleCount(0, PixelConfig::RGBA_8888), 1); - EXPECT_EQ(caps.getSampleCount(5, PixelConfig::ALPHA_8), 1); + EXPECT_EQ(caps.getSampleCount(5, PixelFormat::RGBA_8888), 8); + EXPECT_EQ(caps.getSampleCount(10, PixelFormat::RGBA_8888), 1); + EXPECT_EQ(caps.getSampleCount(0, PixelFormat::RGBA_8888), 1); + EXPECT_EQ(caps.getSampleCount(5, PixelFormat::ALPHA_8), 1); } { ++i; diff --git a/test/PAGBlendTest.cpp b/test/PAGBlendTest.cpp index 8e882ab1b2..05323a2596 100644 --- a/test/PAGBlendTest.cpp +++ b/test/PAGBlendTest.cpp @@ -51,13 +51,13 @@ PAG_TEST_F(PAGBlendTest, Blend) { } } -tgfx::GLTextureInfo GetBottomLeftImage(std::shared_ptr device, int width, int height) { +tgfx::GLSampler GetBottomLeftImage(std::shared_ptr device, int width, int height) { auto context = device->lockContext(); auto gl = GLContext::Unwrap(context); - tgfx::GLTextureInfo textureInfo; + tgfx::GLSampler textureInfo; CreateGLTexture(gl, width, height, &textureInfo); - tgfx::BackendTexture backendTexture(textureInfo, width, height); - auto surface = PAGSurface::MakeFrom(ToPAG(backendTexture), ImageOrigin::BottomLeft); + auto backendTexture = ToBackendTexture(textureInfo, width, height); + auto surface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); device->unlock(); auto composition = PAGComposition::Make(1080, 1920); auto imageLayer = PAGImageLayer::Make(1080, 1920, 1000000); @@ -80,10 +80,10 @@ PAG_TEST_F(PAGBlendTest, CopyDstTexture) { auto context = device->lockContext(); ASSERT_TRUE(context != nullptr); auto gl = GLContext::Unwrap(context); - tgfx::GLTextureInfo textureInfo; + tgfx::GLSampler textureInfo; CreateGLTexture(gl, width, height, &textureInfo); - auto backendTexture = tgfx::BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(ToPAG(backendTexture), ImageOrigin::BottomLeft); + auto backendTexture = ToBackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); device->unlock(); auto pagPlayer = std::make_shared(); pagPlayer->setSurface(pagSurface); @@ -111,12 +111,12 @@ PAG_TEST_F(PAGBlendTest, TextureBottomLeft) { auto context = device->lockContext(); ASSERT_TRUE(context != nullptr); auto gl = GLContext::Unwrap(context); - auto backendTexture = tgfx::BackendTexture(replaceTextureInfo, width, height); - auto replaceImage = PAGImage::FromTexture(ToPAG(backendTexture), ImageOrigin::BottomLeft); - tgfx::GLTextureInfo textureInfo; + auto backendTexture = ToBackendTexture(replaceTextureInfo, width, height); + auto replaceImage = PAGImage::FromTexture(backendTexture, ImageOrigin::BottomLeft); + tgfx::GLSampler textureInfo; CreateGLTexture(gl, width, height, &textureInfo); - backendTexture = tgfx::BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(ToPAG(backendTexture), ImageOrigin::TopLeft); + backendTexture = ToBackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::TopLeft); device->unlock(); auto pagPlayer = std::make_shared(); @@ -146,15 +146,15 @@ PAG_TEST_F(PAGBlendTest, BothBottomLeft) { auto replaceTextureInfo = GetBottomLeftImage(device, width, height); auto context = device->lockContext(); ASSERT_TRUE(context != nullptr); - auto backendTexture = tgfx::BackendTexture(replaceTextureInfo, width / 2, height / 2); - auto replaceImage = PAGImage::FromTexture(ToPAG(backendTexture), ImageOrigin::BottomLeft); + auto backendTexture = ToBackendTexture(replaceTextureInfo, width / 2, height / 2); + auto replaceImage = PAGImage::FromTexture(backendTexture, ImageOrigin::BottomLeft); replaceImage->setMatrix( Matrix::MakeTrans(static_cast(width) * 0.1, static_cast(height) * 0.2)); auto gl = GLContext::Unwrap(context); - tgfx::GLTextureInfo textureInfo; + tgfx::GLSampler textureInfo = {}; CreateGLTexture(gl, width, height, &textureInfo); - backendTexture = tgfx::BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(ToPAG(backendTexture), ImageOrigin::BottomLeft); + backendTexture = ToBackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); device->unlock(); auto composition = PAGComposition::Make(width, height); diff --git a/test/PAGReadPixelsTest.cpp b/test/PAGReadPixelsTest.cpp index a37b43215a..8697abdb04 100644 --- a/test/PAGReadPixelsTest.cpp +++ b/test/PAGReadPixelsTest.cpp @@ -24,6 +24,7 @@ #include "framework/utils/PAGTestUtils.h" #include "gpu/Surface.h" #include "gpu/opengl/GLDevice.h" +#include "gpu/opengl/GLTexture.h" #include "gpu/opengl/GLUtil.h" namespace pag { @@ -224,11 +225,12 @@ PAG_TEST(PAGReadPixelsTest, TestSurfaceReadPixels) { CHECK_PIXELS(AlphaRectInfo, pixels, "Surface_alpha_to_alpha_100_-100"); auto gl = GLContext::Unwrap(context); - tgfx::GLTextureInfo textureInfo = {}; + tgfx::GLSampler textureInfo = {}; result = CreateGLTexture(gl, width, height, &textureInfo); ASSERT_TRUE(result); - auto backendTexture = tgfx::BackendTexture(textureInfo, width, height); - surface = Surface::MakeFrom(context, backendTexture, tgfx::ImageOrigin::BottomLeft); + auto glTexture = + GLTexture::MakeFrom(context, textureInfo, width, height, tgfx::ImageOrigin::BottomLeft); + surface = Surface::MakeFrom(context, glTexture); ASSERT_TRUE(surface != nullptr); canvas = surface->getCanvas(); canvas->clear(); diff --git a/test/PAGSurfaceTest.cpp b/test/PAGSurfaceTest.cpp index 243b1b17ae..dd1a655f2f 100644 --- a/test/PAGSurfaceTest.cpp +++ b/test/PAGSurfaceTest.cpp @@ -40,10 +40,10 @@ PAG_TEST(PAGSurfaceTest, FromTexture) { ASSERT_TRUE(context != nullptr); auto gl = GLContext::Unwrap(context); auto glVersion = gl->caps->version; - tgfx::GLTextureInfo textureInfo; + tgfx::GLSampler textureInfo; CreateGLTexture(gl, width, height, &textureInfo); - auto backendTexture = tgfx::BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(ToPAG(backendTexture), ImageOrigin::TopLeft); + auto backendTexture = ToBackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::TopLeft); auto nativeHandle = GLDevice::CurrentNativeHandle(); device->unlock(); auto glDevice = std::static_pointer_cast(pagSurface->drawable->getDevice()); @@ -92,10 +92,10 @@ PAG_TEST(PAGSurfaceTest, Mask) { auto context = device->lockContext(); ASSERT_TRUE(context != nullptr); auto gl = GLContext::Unwrap(context); - tgfx::GLTextureInfo textureInfo; + tgfx::GLSampler textureInfo; CreateGLTexture(gl, width, height, &textureInfo); - auto backendTexture = tgfx::BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(ToPAG(backendTexture), ImageOrigin::BottomLeft); + auto backendTexture = ToBackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); device->unlock(); auto pagPlayer = std::make_shared(); diff --git a/tgfx/include/gpu/Backend.h b/tgfx/include/gpu/Backend.h index 8189429e59..8869fbf0cb 100644 --- a/tgfx/include/gpu/Backend.h +++ b/tgfx/include/gpu/Backend.h @@ -18,9 +18,6 @@ #pragma once -#include "gpu/metal/MtlTypes.h" -#include "gpu/opengl/GLTypes.h" - namespace tgfx { /** * Possible GPU backend APIs that may be used by TGFX. @@ -35,178 +32,4 @@ enum class Backend { METAL, VULKAN, }; - -/** - * Wrapper class for passing into and receiving data from TGFX about a backend texture object. - */ -class BackendTexture { - public: - /** - * Creates an invalid backend texture. - */ - BackendTexture() : _width(0), _height(0) { - } - - /** - * Creates an OpenGL backend texture. - */ - BackendTexture(const GLTextureInfo& glInfo, int width, int height); - - /** - * Creates an Metal backend texture. - */ - BackendTexture(const MtlTextureInfo& mtlInfo, int width, int height); - - BackendTexture(const BackendTexture& that); - - BackendTexture& operator=(const BackendTexture& that); - - /** - * Returns true if the backend texture has been initialized. - */ - bool isValid() const { - return _width > 0 && _height > 0; - } - - /** - * Returns the width of this texture. - */ - int width() const { - return _width; - } - - /** - * Returns the height of this texture. - */ - int height() const { - return _height; - } - - /** - * Returns the backend API of this texture. - */ - Backend backend() const { - return _backend; - } - - /** - * If the backend API is GL, copies a snapshot of the GLTextureInfo struct into the passed in - * pointer and returns true. Otherwise returns false if the backend API is not GL. - */ - bool getGLTextureInfo(GLTextureInfo* glTextureInfo) const; - - /** - * If the backend API is Metal, copies a snapshot of the GrMtlTextureInfo struct into the passed - * in pointer and returns true. Otherwise returns false if the backend API is not Metal. - */ - bool getMtlTextureInfo(MtlTextureInfo* mtlTextureInfo) const; - - private: - Backend _backend = Backend::MOCK; - int _width = 0; - int _height = 0; - - union { - GLTextureInfo glInfo; - MtlTextureInfo mtlInfo; - }; -}; - -/** - * Wrapper class for passing into and receiving data from TGFX about a backend render target object. - */ -class BackendRenderTarget { - public: - /** - * Creates an invalid backend render target. - */ - BackendRenderTarget() : _width(0), _height(0) { - } - - /** - * Creates an OpenGL backend render target. - */ - BackendRenderTarget(const GLFrameBufferInfo& glInfo, int width, int height); - - /** - * Creates an Metal backend render target. - */ - BackendRenderTarget(const MtlTextureInfo& mtlInfo, int width, int height); - - BackendRenderTarget(const BackendRenderTarget& that); - - BackendRenderTarget& operator=(const BackendRenderTarget&); - - /** - * Returns true if the backend texture has been initialized. - */ - bool isValid() const { - return _width > 0 && _height > 0; - } - - /** - * Returns the width of this render target. - */ - int width() const { - return _width; - } - - /** - * Returns the height of this render target. - */ - int height() const { - return _height; - } - - /** - * Returns the backend API of this render target. - */ - Backend backend() const { - return _backend; - } - - /** - * If the backend API is GL, copies a snapshot of the GLFramebufferInfo struct into the passed - * in pointer and returns true. Otherwise returns false if the backend API is not GL. - */ - bool getGLFramebufferInfo(GLFrameBufferInfo* glFrameBufferInfo) const; - - /** - * If the backend API is Metal, copies a snapshot of the MtlTextureInfo struct into the passed - * in pointer and returns true. Otherwise returns false if the backend API is not Metal. - */ - bool getMtlTextureInfo(MtlTextureInfo* mtlTextureInfo) const; - - private: - Backend _backend = Backend::MOCK; - int _width = 0; - int _height = 0; - union { - GLFrameBufferInfo glInfo; - MtlTextureInfo mtlInfo; - }; -}; - -/** - * Wrapper class for passing into and receiving data from TGFX about a backend semaphore object. - */ -class BackendSemaphore { - public: - BackendSemaphore(); - - bool isInitialized() const { - return _isInitialized; - } - - void initGL(void* sync); - - void* glSync() const; - - private: - Backend _backend = Backend::MOCK; - union { - void* _glSync; - }; - bool _isInitialized; -}; } // namespace tgfx diff --git a/tgfx/include/gpu/opengl/GLTypes.h b/tgfx/include/gpu/PixelFormat.h similarity index 64% rename from tgfx/include/gpu/opengl/GLTypes.h rename to tgfx/include/gpu/PixelFormat.h index 01add8a7fe..ca1e94cc4c 100644 --- a/tgfx/include/gpu/opengl/GLTypes.h +++ b/tgfx/include/gpu/PixelFormat.h @@ -20,35 +20,27 @@ namespace tgfx { /** - * Types for interacting with GL textures created externally to TGFX. + * Describes the possible pixel formats of a TextureSampler. */ -struct GLTextureInfo { +enum class PixelFormat { /** - * the id of this texture. + * Pixel with 8 bits for alpha. Each pixel is stored on 1 bytes. */ - unsigned id = 0; - /** - * The target of this texture. - */ - unsigned target = 0x0DE1; // GL_TEXTURE_2D; + ALPHA_8, + /** - * The pixel format of this texture. + * Pixel with 8 bits for grayscale. Each pixel is stored on 1 bytes. */ - unsigned format = 0x8058; // GL_RGBA8; -}; + GRAY_8, -/** - * Types for interacting with GL frame buffers created externally to TGFX. - */ -struct GLFrameBufferInfo { /** - * The id of this frame buffer. + * Pixel with 8 bits for red, green. Each pixel is stored on 2 bytes. */ - unsigned id = 0; + RG_88, /** - * The pixel format of this frame buffer. + * Pixel with 8 bits for red, green, blue, alpha. Each pixel is stored on 4 bytes. */ - unsigned format = 0x8058; // GL_RGBA8; + RGBA_8888 }; } // namespace tgfx diff --git a/tgfx/include/gpu/RenderTarget.h b/tgfx/include/gpu/RenderTarget.h new file mode 100644 index 0000000000..8e65574f04 --- /dev/null +++ b/tgfx/include/gpu/RenderTarget.h @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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/Texture.h" + +namespace tgfx { +/** + * RenderTarget represents a 2D buffer of pixels that can be rendered to. + */ +class RenderTarget : public Resource { + public: + /** + * Returns the display width of the render target. + */ + int width() const { + return _width; + } + + /** + * Returns the display height of the render target. + */ + int height() const { + return _height; + } + + /** + * Returns the origin of the render target, either ImageOrigin::TopLeft or + * ImageOrigin::BottomLeft. + */ + ImageOrigin origin() const { + return _origin; + } + + /** + * Returns the sample count of the render target. + */ + int sampleCount() const { + return _sampleCount; + } + + protected: + RenderTarget(int width, int height, ImageOrigin origin, int sampleCount = 1) + : _width(width), _height(height), _origin(origin), _sampleCount(sampleCount) { + } + + private: + int _width = 0; + int _height = 0; + ImageOrigin _origin = ImageOrigin::TopLeft; + int _sampleCount = 1; +}; +} // namespace tgfx diff --git a/tgfx/src/gpu/PixelConfig.h b/tgfx/include/gpu/Semaphore.h similarity index 89% rename from tgfx/src/gpu/PixelConfig.h rename to tgfx/include/gpu/Semaphore.h index d2e9c3acd3..a2460740c1 100644 --- a/tgfx/src/gpu/PixelConfig.h +++ b/tgfx/include/gpu/Semaphore.h @@ -19,5 +19,11 @@ #pragma once namespace tgfx { -enum class PixelConfig { ALPHA_8, Gray_8, RG_88, RGBA_8888 }; +/** + * Wrapper class for a backend semaphore object. + */ +class Semaphore { + public: + virtual ~Semaphore() = default; +}; } // namespace tgfx diff --git a/tgfx/include/gpu/Surface.h b/tgfx/include/gpu/Surface.h index 557a4e0f9e..bc4563a0b0 100644 --- a/tgfx/include/gpu/Surface.h +++ b/tgfx/include/gpu/Surface.h @@ -20,6 +20,8 @@ #include "core/ImageInfo.h" #include "gpu/Canvas.h" +#include "gpu/RenderTarget.h" +#include "gpu/Semaphore.h" namespace tgfx { /** @@ -36,8 +38,6 @@ class Canvas; class Context; -class Texture; - /** * Surface is responsible for managing the pixels that a canvas draws into. Surface takes care of * allocating a Canvas that will draw into the surface. Call surface->getCanvas() to use that @@ -49,26 +49,25 @@ class Surface { public: /** * Creates a new Surface on GPU indicated by context. Allocates memory for pixels, based on the - * width, height and color type (alphaOnly). Return nullptr if alphaOnly is not supported or the - * size is zero. + * width, height and color type (alphaOnly). A Surface with MSAA enabled is returned if the + * sampleCount is greater than 1. Return nullptr if alphaOnly is not supported or the size is + * zero. */ static std::shared_ptr Make(Context* context, int width, int height, bool alphaOnly = false, int sampleCount = 1); /** - * Wraps a backed render target into Surface. Caller must ensure renderTarget is valid for the - * lifetime of returned Surface. + * Wraps a render target into Surface. Returns nullptr if renderTarget is nullptr. */ static std::shared_ptr MakeFrom(Context* context, - const BackendRenderTarget& renderTarget, - ImageOrigin origin); + std::shared_ptr renderTarget); /** - * Wraps a backed texture into Surface. Caller must ensure backendTexture is valid for the - * lifetime of returned Surface. + * Wraps a texture into Surface. A Surface with MSAA enabled is returned if the sampleCount is + * greater than 1. Returns nullptr if the specified texture is not renderable. */ - static std::shared_ptr MakeFrom(Context* context, const BackendTexture& backendTexture, - ImageOrigin origin); + static std::shared_ptr MakeFrom(Context* context, std::shared_ptr texture, + int sampleCount = 1); explicit Surface(Context* context); @@ -111,8 +110,13 @@ class Surface { virtual ImageOrigin origin() const = 0; /** - * Retrieves the texture which Surface renders onto. Return nullptr if Surface was made from a - * BackendRenderTarget. + * Retrieves the render target that the surface renders to. + */ + virtual std::shared_ptr getRenderTarget() const = 0; + + /** + * Retrieves the texture that the surface renders to. Return nullptr if the surface was made from + * a RenderTarget. */ virtual std::shared_ptr getTexture() const = 0; @@ -129,7 +133,7 @@ class Surface { * GPU back-end will not wait on the passed semaphore, and the client will still own the * semaphore. Returns true if GPU is waiting on the semaphore. */ - virtual bool wait(const BackendSemaphore& waitSemaphore) = 0; + virtual bool wait(const Semaphore* waitSemaphore) = 0; /** * Apply all pending changes to the render target immediately. After issuing all commands, the @@ -140,7 +144,7 @@ class Surface { * If false is returned, the GPU back-end did not create or add a semaphore to signal on the GPU; * the caller should not instruct the GPU to wait on the semaphore. */ - virtual bool flush(BackendSemaphore* signalSemaphore) = 0; + virtual bool flush(Semaphore* signalSemaphore) = 0; /** * Apply all pending changes to the render target immediately. diff --git a/tgfx/include/gpu/Texture.h b/tgfx/include/gpu/Texture.h index 14b2f09a82..0d61117a7b 100644 --- a/tgfx/include/gpu/Texture.h +++ b/tgfx/include/gpu/Texture.h @@ -31,33 +31,46 @@ class TextureSampler; */ class Texture : public Resource { public: - /** - * Creates a new texture which wraps the BackendTexture. - */ - static std::shared_ptr MakeFrom(Context* context, const BackendTexture& backendTexture, - ImageOrigin origin); - /** * Creates a single-plane texture from a hardware buffer. The type of hardwareBuffer should be * either AHardwareBuffer* on android platform or CVPixelBufferRef on apple platform. The returned - * Texture takes a reference on the buffer. + * Texture takes a reference on the buffer. Returns nullptr if any of the parameters is not valid. */ static std::shared_ptr MakeFrom(Context* context, void* hardwareBuffer); /** - * Creates a new texture from specified pixels data with each pixel stored as 32-bit RGBA data. + * Creates a new texture from the specified pixel data with each pixel stored as 32-bit RGBA + * data. Returns nullptr if any of the parameters is not valid. */ static std::shared_ptr MakeRGBA(Context* context, int width, int height, void* pixels, size_t rowBytes, ImageOrigin origin = ImageOrigin::TopLeft); + /** + * Creates a empty texture with each pixel stored as 32-bit RGBA data. Returns nullptr if any of + * the parameters is not valid. + */ + static std::shared_ptr MakeRGBA(Context* context, int width, int height, + ImageOrigin origin = ImageOrigin::TopLeft) { + return MakeRGBA(context, width, height, nullptr, 0, origin); + } /** - * Creates a new texture from specified pixels data with each pixel stored as a single - * translucency (alpha) channel. + * Creates a new texture from the specified pixel data with each pixel stored as a single + * translucency (alpha) channel. Returns nullptr if any of the parameters is not valid or the + * backend does not support creating alpha only textures. */ static std::shared_ptr MakeAlpha(Context* context, int width, int height, void* pixels, size_t rowBytes, ImageOrigin origin = ImageOrigin::TopLeft); + /** + * Creates a empty texture with each pixel stored as a single translucency (alpha) channel. + * Returns nullptr if any of the parameters is not valid or the backend does not support creating + * alpha only textures. + */ + static std::shared_ptr MakeAlpha(Context* context, int width, int height, + ImageOrigin origin = ImageOrigin::TopLeft) { + return MakeAlpha(context, width, height, nullptr, 0, origin); + } Texture(int width, int height, ImageOrigin origin) : _width(width), _height(height), _origin(origin) { @@ -95,7 +108,7 @@ class Texture : public Resource { virtual size_t memoryUsage() const = 0; /** - * Returns texture sampler. + * Returns the default texture sampler. */ virtual const TextureSampler* getSampler() const = 0; diff --git a/tgfx/src/gpu/TextureSampler.h b/tgfx/include/gpu/TextureSampler.h similarity index 80% rename from tgfx/src/gpu/TextureSampler.h rename to tgfx/include/gpu/TextureSampler.h index ca89a2ab64..9ddae9d19c 100644 --- a/tgfx/src/gpu/TextureSampler.h +++ b/tgfx/include/gpu/TextureSampler.h @@ -20,20 +20,26 @@ #include "core/BytesKey.h" #include "gpu/Context.h" -#include "gpu/PixelConfig.h" +#include "gpu/PixelFormat.h" namespace tgfx { +/** + * TextureSampler stores the sampling parameters for a backend texture uint. + */ class TextureSampler { public: - TextureSampler() = default; - virtual ~TextureSampler() = default; - explicit TextureSampler(PixelConfig config) : config(config) { - } - + /** + * The pixel format of the sampler. + */ + PixelFormat format = PixelFormat::RGBA_8888; + + protected: virtual void computeKey(Context* context, BytesKey* bytesKey) const = 0; - PixelConfig config = PixelConfig::RGBA_8888; + friend class FragmentProcessor; + + friend class Pipeline; }; } // namespace tgfx diff --git a/tgfx/include/gpu/YUVTexture.h b/tgfx/include/gpu/YUVTexture.h index a58d587e54..694ac8a0d5 100644 --- a/tgfx/include/gpu/YUVTexture.h +++ b/tgfx/include/gpu/YUVTexture.h @@ -24,7 +24,7 @@ namespace tgfx { /** - * YUVTexture wraps separate textures in the GPU backend for Y, U, and V planes. + * YUVTexture wraps separate texture units in the GPU backend for Y, U, and V planes. */ class YUVTexture : public Texture { public: diff --git a/tgfx/include/gpu/opengl/GLFrameBuffer.h b/tgfx/include/gpu/opengl/GLFrameBuffer.h new file mode 100644 index 0000000000..16de38d9f9 --- /dev/null +++ b/tgfx/include/gpu/opengl/GLFrameBuffer.h @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Tencent is pleased to support the open source community by making libpag available. +// +// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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/PixelFormat.h" + +namespace tgfx { +/** + * Types for interacting with GL frame buffers. + */ +struct GLFrameBuffer { + /** + * The id of this frame buffer. + */ + unsigned id = 0; + + /** + * The pixel format of this frame buffer. + */ + PixelFormat format = PixelFormat::RGBA_8888; +}; +} // namespace tgfx diff --git a/tgfx/src/gpu/opengl/GLRenderTarget.h b/tgfx/include/gpu/opengl/GLRenderTarget.h similarity index 54% rename from tgfx/src/gpu/opengl/GLRenderTarget.h rename to tgfx/include/gpu/opengl/GLRenderTarget.h index dfdd31f482..afd14c31cc 100644 --- a/tgfx/src/gpu/opengl/GLRenderTarget.h +++ b/tgfx/include/gpu/opengl/GLRenderTarget.h @@ -18,70 +18,70 @@ #pragma once -#include "GLState.h" -#include "GLTexture.h" #include "core/ImageInfo.h" +#include "gpu/RenderTarget.h" +#include "gpu/opengl/GLFrameBuffer.h" +#include "gpu/opengl/GLTexture.h" namespace tgfx { +class GLInterface; + /** - * GLRenderTarget represents a 2D buffer of pixels that can be rendered to. + * Represents a OpenGL 2D buffer of pixels that can be rendered to. */ -class GLRenderTarget : public Resource { +class GLRenderTarget : public RenderTarget { public: /** - * Wraps a BackendRenderTarget into GLRenderTarget. Caller must ensure the BackendRenderTarget is - * valid for the lifetime of returned render target. + * Wraps an OpenGL frame buffer into GLRenderTarget. Please pass the number of samples-per-pixel + * in the sampleCount parameter if the frame buffer was constructed with MSAA enabled. Caller must + * ensure the backend frame buffer is valid for the lifetime of returned GLRenderTarget. */ static std::shared_ptr MakeFrom(Context* context, - const BackendRenderTarget& renderTarget, - ImageOrigin origin); - - /** - * Creates a new render target which uses specified texture as pixel storage. Caller must ensure - * texture is valid for the lifetime of returned render target. - */ - static std::shared_ptr MakeFrom(Context* context, GLTexture* texture, + const GLFrameBuffer& frameBuffer, int width, + int height, ImageOrigin origin, int sampleCount = 1); /** - * Returns the display width of this render target. + * Wraps an OpenGL frame buffer into GLRenderTarget. Please pass the number of samples-per-pixel + * in the sampleCount parameter if the frame buffer was constructed with MSAA enabled. The + * returned GLRenderTarget takes ownership of the backend frame buffer. */ - int width() const { - return _width; - } + static std::shared_ptr MakeAdopted(Context* context, + const GLFrameBuffer& frameBuffer, int width, + int height, ImageOrigin origin, + int sampleCount = 1); /** - * Returns the display height of this render target. + * Returns the GLFrameBuffer associated with this render target. */ - int height() const { - return _height; - } - - /** - * Returns the origin of this render target, either ImageOrigin::TopLeft or - * ImageOrigin::BottomLeft. - */ - ImageOrigin origin() const { - return _origin; - } - - GLFrameBufferInfo getGLInfo() const { + GLFrameBuffer glFrameBuffer() const { return renderTargetFBInfo; } - int sampleCount() const { - return _sampleCount; - } + protected: + void onRelease(Context* context) override; - bool usesMSAA() const { - return _sampleCount > 1; - } + private: + GLFrameBuffer textureFBInfo = {}; + GLFrameBuffer renderTargetFBInfo = {}; + unsigned msRenderBufferID = 0; + unsigned textureTarget = 0; + bool externalTexture = false; /** - * Replacing all pixels with transparent color. + * Creates a new render target which uses specified texture as pixel storage. Caller must ensure + * texture is valid for the lifetime of returned render target. */ + static std::shared_ptr MakeFrom(Context* context, const GLTexture* texture, + int sampleCount = 1); + + GLRenderTarget(int width, int height, ImageOrigin origin, int sampleCount, + GLFrameBuffer frameBuffer, unsigned textureTarget = 0); + void clear(const GLInterface* gl) const; + void resolve(Context* context) const; + /** * Copies a rect of pixels to dstPixels with specified color type, alpha type and row bytes. Copy * starts at (srcX, srcY), and does not exceed Surface (width(), height()). Pixels are copied @@ -90,24 +90,10 @@ class GLRenderTarget : public Resource { bool readPixels(Context* context, const ImageInfo& dstInfo, void* dstPixels, int srcX = 0, int srcY = 0) const; - void resolve(Context* context) const; - - protected: - void onRelease(Context* context) override; - - private: - int _width = 0; - int _height = 0; - ImageOrigin _origin = ImageOrigin::TopLeft; - int _sampleCount = 1; - GLFrameBufferInfo textureFBInfo = {}; - GLFrameBufferInfo renderTargetFBInfo = {}; - unsigned msRenderBufferID = 0; - unsigned textureTarget = 0; + friend class GLSurface; - GLRenderTarget(int width, int height, ImageOrigin origin, GLFrameBufferInfo info, - unsigned textureTarget = 0); + friend class GLCanvas; - friend class GLSurface; + friend class Surface; }; } // namespace tgfx diff --git a/tgfx/src/gpu/opengl/GLTextureSampler.h b/tgfx/include/gpu/opengl/GLSampler.h similarity index 78% rename from tgfx/src/gpu/opengl/GLTextureSampler.h rename to tgfx/include/gpu/opengl/GLSampler.h index e592226dd6..ae122b778f 100644 --- a/tgfx/src/gpu/opengl/GLTextureSampler.h +++ b/tgfx/include/gpu/opengl/GLSampler.h @@ -21,16 +21,22 @@ #include "gpu/TextureSampler.h" namespace tgfx { -class GLTextureSampler : public TextureSampler { +/** + * Defines the sampling parameters for an OpenGL texture uint. + */ +class GLSampler : public TextureSampler { public: - GLTextureSampler() = default; + /** + * The OpenGL texture id of the sampler. + */ + unsigned id = 0; - GLTextureSampler(PixelConfig config, GLTextureInfo textureInfo) - : TextureSampler(config), glInfo(textureInfo) { - } + /** + * The OpenGL texture target of the sampler. + */ + unsigned target = 0x0DE1; // GL_TEXTURE_2D; + protected: void computeKey(Context* context, BytesKey* bytesKey) const override; - - GLTextureInfo glInfo = {}; }; } // namespace tgfx diff --git a/tgfx/include/gpu/metal/MtlTypes.h b/tgfx/include/gpu/opengl/GLSemaphore.h similarity index 83% rename from tgfx/include/gpu/metal/MtlTypes.h rename to tgfx/include/gpu/opengl/GLSemaphore.h index f1f7f60f50..1c18a053e0 100644 --- a/tgfx/include/gpu/metal/MtlTypes.h +++ b/tgfx/include/gpu/opengl/GLSemaphore.h @@ -18,15 +18,18 @@ #pragma once +#include "gpu/Semaphore.h" + namespace tgfx { + /** - * Types for interacting with Metal resources created externally to TGFX. Holds the MTLTexture as a - * const void*. + * Types for interacting with OpenGL semaphore object. */ -struct MtlTextureInfo { +class GLSemaphore : public Semaphore { + public: /** - * Pointer to MTLTexture. + * Holds the GLsync as a void*. */ - const void* texture = nullptr; + void* glSync = nullptr; }; } // namespace tgfx diff --git a/tgfx/src/gpu/opengl/GLTexture.h b/tgfx/include/gpu/opengl/GLTexture.h similarity index 58% rename from tgfx/src/gpu/opengl/GLTexture.h rename to tgfx/include/gpu/opengl/GLTexture.h index e99c5f5c49..72c282a751 100644 --- a/tgfx/src/gpu/opengl/GLTexture.h +++ b/tgfx/include/gpu/opengl/GLTexture.h @@ -18,26 +18,28 @@ #pragma once -#include "GLContext.h" -#include "GLTextureSampler.h" #include "gpu/Texture.h" +#include "gpu/opengl/GLSampler.h" namespace tgfx { +/** + * Describes a two dimensional array of pixels in the OpenGL backend for drawing. + */ class GLTexture : public Texture { public: - static GLTextureInfo Unwrap(const Texture* texture); - /** - * Creates a new texture with each pixel stored as a single translucency (alpha) channel. + * Creates a new GLTexture which wraps the specified backend texture. Caller must ensure the + * backend texture is valid for the lifetime of returned GLTexture. */ - static std::shared_ptr MakeAlpha(Context* context, int width, int height, - ImageOrigin origin = ImageOrigin::TopLeft); + static std::shared_ptr MakeFrom(Context* context, const GLSampler& sampler, int width, + int height, ImageOrigin origin); /** - * Creates a new texture with each pixel stored as 32-bit RGBA data. + * Creates a new GLTexture which wraps the specified backend texture. The returned GLTexture takes + * ownership of the specified backend texture. */ - static std::shared_ptr MakeRGBA(Context* context, int width, int height, - ImageOrigin origin = ImageOrigin::TopLeft); + static std::shared_ptr MakeAdopted(Context* context, const GLSampler& sampler, + int width, int height, ImageOrigin origin); Point getTextureCoord(float x, float y) const override; @@ -45,12 +47,15 @@ class GLTexture : public Texture { return &sampler; } - const GLTextureInfo& getGLInfo() const { - return sampler.glInfo; + /** + * Returns the GLSampler associated with the texture. + */ + const GLSampler& glSampler() const { + return sampler; } protected: - GLTextureSampler sampler = {}; + GLSampler sampler = {}; GLTexture(int width, int height, ImageOrigin origin); diff --git a/tgfx/src/gpu/opengl/GLYUVTexture.h b/tgfx/include/gpu/opengl/GLYUVTexture.h similarity index 88% rename from tgfx/src/gpu/opengl/GLYUVTexture.h rename to tgfx/include/gpu/opengl/GLYUVTexture.h index 5d6d2d1d75..c2f7936516 100644 --- a/tgfx/src/gpu/opengl/GLYUVTexture.h +++ b/tgfx/include/gpu/opengl/GLYUVTexture.h @@ -18,12 +18,13 @@ #pragma once -#include "GLContext.h" -#include "GLTextureSampler.h" #include "gpu/YUVTexture.h" +#include "gpu/opengl/GLSampler.h" namespace tgfx { -struct YUVConfig; +/** + * GLYUVTexture wraps separate texture units in the OpenGL backend for Y, U, and V planes. + */ class GLYUVTexture : public YUVTexture { public: Point getTextureCoord(float x, float y) const override; @@ -34,12 +35,8 @@ class GLYUVTexture : public YUVTexture { const TextureSampler* getSamplerAt(size_t index) const override; - size_t planeCount() const { - return samplerCount(); - } - protected: - std::vector samplers = {}; + std::vector samplers = {}; GLYUVTexture(YUVColorSpace colorSpace, YUVColorRange colorRange, int width, int height); diff --git a/tgfx/src/gpu/Backend.cpp b/tgfx/src/gpu/Backend.cpp deleted file mode 100644 index 9542f55d34..0000000000 --- a/tgfx/src/gpu/Backend.cpp +++ /dev/null @@ -1,136 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////////////// -// -// Tencent is pleased to support the open source community by making libpag available. -// -// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file -// except in compliance with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 "gpu/Backend.h" - -namespace tgfx { -BackendTexture::BackendTexture(const GLTextureInfo& glInfo, int width, int height) - : _backend(Backend::OPENGL), _width(width), _height(height), glInfo(glInfo) { -} - -BackendTexture::BackendTexture(const MtlTextureInfo& mtlInfo, int width, int height) - : _backend(Backend::METAL), _width(width), _height(height), mtlInfo(mtlInfo) { -} - -BackendTexture::BackendTexture(const BackendTexture& that) { - *this = that; -} - -BackendTexture& BackendTexture::operator=(const BackendTexture& that) { - if (!that.isValid()) { - _width = _height = 0; - return *this; - } - _width = that._width; - _height = that._height; - _backend = that._backend; - switch (that._backend) { - case Backend::OPENGL: - glInfo = that.glInfo; - break; - case Backend::METAL: - mtlInfo = that.mtlInfo; - break; - default: - break; - } - return *this; -} - -bool BackendTexture::getGLTextureInfo(GLTextureInfo* glTextureInfo) const { - if (!isValid() || _backend != Backend::OPENGL) { - return false; - } - *glTextureInfo = glInfo; - return true; -} - -bool BackendTexture::getMtlTextureInfo(MtlTextureInfo* mtlTextureInfo) const { - if (!isValid() || _backend != Backend::METAL) { - return false; - } - *mtlTextureInfo = mtlInfo; - return true; -} - -BackendRenderTarget::BackendRenderTarget(const GLFrameBufferInfo& glInfo, int width, int height) - : _backend(Backend::OPENGL), _width(width), _height(height), glInfo(glInfo) { -} - -BackendRenderTarget::BackendRenderTarget(const MtlTextureInfo& mtlInfo, int width, int height) - : _backend(Backend::METAL), _width(width), _height(height), mtlInfo(mtlInfo) { -} - -BackendRenderTarget::BackendRenderTarget(const BackendRenderTarget& that) { - *this = that; -} - -BackendRenderTarget& BackendRenderTarget::operator=(const BackendRenderTarget& that) { - if (!that.isValid()) { - _width = _height = 0; - return *this; - } - _width = that._width; - _height = that._height; - _backend = that._backend; - switch (that._backend) { - case Backend::OPENGL: - glInfo = that.glInfo; - break; - case Backend::METAL: - mtlInfo = that.mtlInfo; - break; - default: - break; - } - return *this; -} - -bool BackendRenderTarget::getGLFramebufferInfo(GLFrameBufferInfo* glFrameBufferInfo) const { - if (!isValid() || _backend != Backend::OPENGL) { - return false; - } - *glFrameBufferInfo = glInfo; - return true; -} - -bool BackendRenderTarget::getMtlTextureInfo(MtlTextureInfo* mtlTextureInfo) const { - if (!isValid() || _backend != Backend::METAL) { - return false; - } - *mtlTextureInfo = mtlInfo; - return true; -} - -BackendSemaphore::BackendSemaphore() - : _backend(Backend::MOCK), _glSync(nullptr), _isInitialized(false) { -} - -void BackendSemaphore::initGL(void* sync) { - _backend = Backend::OPENGL; - _glSync = sync; - _isInitialized = true; -} - -void* BackendSemaphore::glSync() const { - if (!_isInitialized || _backend != Backend::OPENGL) { - return nullptr; - } - return _glSync; -} -} // namespace tgfx \ No newline at end of file diff --git a/tgfx/src/gpu/GeometryProcessor.h b/tgfx/src/gpu/GeometryProcessor.h index fe0acb98a2..7cf8173815 100644 --- a/tgfx/src/gpu/GeometryProcessor.h +++ b/tgfx/src/gpu/GeometryProcessor.h @@ -21,7 +21,7 @@ #include #include "Processor.h" #include "ShaderVar.h" -#include "TextureSampler.h" +#include "gpu/TextureSampler.h" namespace tgfx { class GLGeometryProcessor; diff --git a/tgfx/src/gpu/Surface.cpp b/tgfx/src/gpu/Surface.cpp index 56a0f66bbc..4d30aad182 100644 --- a/tgfx/src/gpu/Surface.cpp +++ b/tgfx/src/gpu/Surface.cpp @@ -17,9 +17,11 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include "gpu/Surface.h" +#include "core/utils/Log.h" namespace tgfx { Surface::Surface(Context* context) : context(context) { + DEBUG_ASSERT(context != nullptr); } bool Surface::readPixels(const ImageInfo& dstInfo, void* dstPixels, int srcX, int srcY) const { diff --git a/tgfx/src/gpu/UniformHandler.h b/tgfx/src/gpu/UniformHandler.h index b27a13fb39..58c96f5c83 100644 --- a/tgfx/src/gpu/UniformHandler.h +++ b/tgfx/src/gpu/UniformHandler.h @@ -21,7 +21,7 @@ #include "ResourceHandle.h" #include "ShaderVar.h" #include "Swizzle.h" -#include "TextureSampler.h" +#include "gpu/TextureSampler.h" namespace tgfx { static constexpr char NO_MANGLE_PREFIX[] = "tgfx_"; diff --git a/tgfx/src/gpu/opengl/GLCanvas.cpp b/tgfx/src/gpu/opengl/GLCanvas.cpp index 79139ce672..6240f60990 100644 --- a/tgfx/src/gpu/opengl/GLCanvas.cpp +++ b/tgfx/src/gpu/opengl/GLCanvas.cpp @@ -34,7 +34,8 @@ GLCanvas::GLCanvas(Surface* surface) : Canvas(surface) { } void GLCanvas::clear() { - static_cast(surface)->getRenderTarget()->clear(GLContext::Unwrap(getContext())); + auto renderTarget = std::static_pointer_cast(surface->getRenderTarget()); + renderTarget->clear(GLContext::Unwrap(getContext())); } void GLCanvas::drawTexture(const Texture* texture, const Texture* mask, bool inverted) { @@ -363,9 +364,9 @@ void GLCanvas::draw(const Rect& localQuad, const Rect& deviceQuad, std::unique_p if (drawer == nullptr) { return; } - auto renderTarget = static_cast(surface)->getRenderTarget(); + auto renderTarget = surface->getRenderTarget(); auto aaType = AAType::None; - if (renderTarget->usesMSAA()) { + if (renderTarget->sampleCount() > 1) { aaType = AAType::MSAA; } else if (aa && !IsPixelAligned(deviceQuad)) { aaType = AAType::Coverage; diff --git a/tgfx/src/gpu/opengl/GLCaps.cpp b/tgfx/src/gpu/opengl/GLCaps.cpp index 8d3ac2fb60..a1169ad240 100644 --- a/tgfx/src/gpu/opengl/GLCaps.cpp +++ b/tgfx/src/gpu/opengl/GLCaps.cpp @@ -180,31 +180,31 @@ GLCaps::GLCaps(const GLInfo& info) { info.getIntegerv(GL::MAX_TEXTURE_SIZE, &maxTextureSize); info.getIntegerv(GL::MAX_TEXTURE_IMAGE_UNITS, &maxFragmentSamplers); initFSAASupport(info); - initConfigMap(info); + initFormatMap(info); } -const TextureFormat& GLCaps::getTextureFormat(PixelConfig config) const { - return configMap.at(config).format; +const TextureFormat& GLCaps::getTextureFormat(PixelFormat pixelFormat) const { + return pixelFormatMap.at(pixelFormat).format; } -const Swizzle& GLCaps::configSwizzle(PixelConfig config) const { - return configMap.at(config).swizzle; +const Swizzle& GLCaps::getSwizzle(PixelFormat pixelFormat) const { + return pixelFormatMap.at(pixelFormat).swizzle; } -const Swizzle& GLCaps::configTextureSwizzle(PixelConfig config) const { - return configMap.at(config).textureSwizzle; +const Swizzle& GLCaps::getTextureSwizzle(PixelFormat pixelFormat) const { + return pixelFormatMap.at(pixelFormat).textureSwizzle; } -const Swizzle& GLCaps::configOutputSwizzle(PixelConfig config) const { - return configMap.at(config).outputSwizzle; +const Swizzle& GLCaps::getOutputSwizzle(PixelFormat pixelFormat) const { + return pixelFormatMap.at(pixelFormat).outputSwizzle; } -int GLCaps::getSampleCount(int requestedCount, PixelConfig config) const { +int GLCaps::getSampleCount(int requestedCount, PixelFormat pixelFormat) const { if (requestedCount <= 1) { return 1; } - auto result = configMap.find(config); - if (result == configMap.end() || result->second.colorSampleCounts.empty()) { + auto result = pixelFormatMap.find(pixelFormat); + if (result == pixelFormatMap.end() || result->second.colorSampleCounts.empty()) { return 1; } for (auto colorSampleCount : result->second.colorSampleCounts) { @@ -272,40 +272,40 @@ void GLCaps::initWebGLSupport(const GLInfo& info) { semaphoreSupport = version >= GL_VER(2, 0); } -void GLCaps::initConfigMap(const GLInfo& info) { - configMap[PixelConfig::RGBA_8888].format.sizedFormat = GL::RGBA8; - configMap[PixelConfig::RGBA_8888].format.externalFormat = GL::RGBA; - configMap[PixelConfig::RGBA_8888].swizzle = Swizzle::RGBA(); +void GLCaps::initFormatMap(const GLInfo& info) { + pixelFormatMap[PixelFormat::RGBA_8888].format.sizedFormat = GL::RGBA8; + pixelFormatMap[PixelFormat::RGBA_8888].format.externalFormat = GL::RGBA; + pixelFormatMap[PixelFormat::RGBA_8888].swizzle = Swizzle::RGBA(); if (textureRedSupport) { - configMap[PixelConfig::ALPHA_8].format.sizedFormat = GL::R8; - configMap[PixelConfig::ALPHA_8].format.externalFormat = GL::RED; - configMap[PixelConfig::ALPHA_8].swizzle = Swizzle::RRRR(); + pixelFormatMap[PixelFormat::ALPHA_8].format.sizedFormat = GL::R8; + pixelFormatMap[PixelFormat::ALPHA_8].format.externalFormat = GL::RED; + pixelFormatMap[PixelFormat::ALPHA_8].swizzle = Swizzle::RRRR(); // Shader output swizzles will default to RGBA. When we've use GL::RED instead of GL::ALPHA to - // implement PixelConfig::ALPHA_8 we need to swizzle the shader outputs so the alpha channel + // implement PixelFormat::ALPHA_8 we need to swizzle the shader outputs so the alpha channel // gets written to the single component. - configMap[PixelConfig::ALPHA_8].outputSwizzle = Swizzle::AAAA(); - configMap[PixelConfig::Gray_8].format.sizedFormat = GL::R8; - configMap[PixelConfig::Gray_8].format.externalFormat = GL::RED; - configMap[PixelConfig::Gray_8].swizzle = Swizzle::RRRA(); - configMap[PixelConfig::RG_88].format.sizedFormat = GL::RG8; - configMap[PixelConfig::RG_88].format.externalFormat = GL::RG; - configMap[PixelConfig::RG_88].swizzle = Swizzle::RGRG(); + pixelFormatMap[PixelFormat::ALPHA_8].outputSwizzle = Swizzle::AAAA(); + pixelFormatMap[PixelFormat::GRAY_8].format.sizedFormat = GL::R8; + pixelFormatMap[PixelFormat::GRAY_8].format.externalFormat = GL::RED; + pixelFormatMap[PixelFormat::GRAY_8].swizzle = Swizzle::RRRA(); + pixelFormatMap[PixelFormat::RG_88].format.sizedFormat = GL::RG8; + pixelFormatMap[PixelFormat::RG_88].format.externalFormat = GL::RG; + pixelFormatMap[PixelFormat::RG_88].swizzle = Swizzle::RGRG(); } else { - configMap[PixelConfig::ALPHA_8].format.sizedFormat = GL::ALPHA8; - configMap[PixelConfig::ALPHA_8].format.externalFormat = GL::ALPHA; - configMap[PixelConfig::ALPHA_8].swizzle = Swizzle::AAAA(); - configMap[PixelConfig::Gray_8].format.sizedFormat = GL::LUMINANCE8; - configMap[PixelConfig::Gray_8].format.externalFormat = GL::LUMINANCE; - configMap[PixelConfig::Gray_8].swizzle = Swizzle::RGBA(); - configMap[PixelConfig::RG_88].format.sizedFormat = GL::LUMINANCE8_ALPHA8; - configMap[PixelConfig::RG_88].format.externalFormat = GL::LUMINANCE_ALPHA; - configMap[PixelConfig::RG_88].swizzle = Swizzle::RARA(); + pixelFormatMap[PixelFormat::ALPHA_8].format.sizedFormat = GL::ALPHA8; + pixelFormatMap[PixelFormat::ALPHA_8].format.externalFormat = GL::ALPHA; + pixelFormatMap[PixelFormat::ALPHA_8].swizzle = Swizzle::AAAA(); + pixelFormatMap[PixelFormat::GRAY_8].format.sizedFormat = GL::LUMINANCE8; + pixelFormatMap[PixelFormat::GRAY_8].format.externalFormat = GL::LUMINANCE; + pixelFormatMap[PixelFormat::GRAY_8].swizzle = Swizzle::RGBA(); + pixelFormatMap[PixelFormat::RG_88].format.sizedFormat = GL::LUMINANCE8_ALPHA8; + pixelFormatMap[PixelFormat::RG_88].format.externalFormat = GL::LUMINANCE_ALPHA; + pixelFormatMap[PixelFormat::RG_88].swizzle = Swizzle::RARA(); } // If we don't have texture swizzle support then the shader generator must insert the // swizzle into shader code. if (!textureSwizzleSupport) { - for (auto& config : configMap) { - config.second.textureSwizzle = config.second.swizzle; + for (auto& item : pixelFormatMap) { + item.second.textureSwizzle = item.second.swizzle; } } // ES 2.0 requires that the internal/external formats match. @@ -313,7 +313,7 @@ void GLCaps::initConfigMap(const GLInfo& info) { (standard == GLStandard::GL || (standard == GLStandard::GLES && version >= GL_VER(3, 0))); bool useSizedRbFormats = standard == GLStandard::GLES || standard == GLStandard::WebGL; - for (auto& item : configMap) { + for (auto& item : pixelFormatMap) { auto& format = item.second.format; format.internalFormatTexImage = useSizedTexFormats ? format.sizedFormat : format.externalFormat; format.internalFormatRenderBuffer = @@ -330,11 +330,11 @@ static bool UsesInternalformatQuery(GLStandard standard, const GLInfo& glInterfa } void GLCaps::initColorSampleCount(const GLInfo& info) { - std::vector pixelConfigs = {PixelConfig::RGBA_8888}; - for (auto config : pixelConfigs) { + std::vector pixelFormats = {PixelFormat::RGBA_8888}; + for (auto pixelFormat : pixelFormats) { if (UsesInternalformatQuery(standard, info, version)) { int count = 0; - unsigned format = configMap[config].format.internalFormatRenderBuffer; + unsigned format = pixelFormatMap[pixelFormat].format.internalFormatRenderBuffer; info.getInternalformativ(GL::RENDERBUFFER, format, GL::NUM_SAMPLE_COUNTS, 1, &count); if (count) { int* temp = new int[count]; @@ -345,9 +345,9 @@ void GLCaps::initColorSampleCount(const GLInfo& info) { } // We initialize our supported values with 1 (no msaa) and reverse the order // returned by GL so that the array is ascending. - configMap[config].colorSampleCounts.push_back(1); + pixelFormatMap[pixelFormat].colorSampleCounts.push_back(1); for (int j = 0; j < count; ++j) { - configMap[config].colorSampleCounts.push_back(temp[count - j - 1]); + pixelFormatMap[pixelFormat].colorSampleCounts.push_back(temp[count - j - 1]); } delete[] temp; } @@ -368,7 +368,7 @@ void GLCaps::initColorSampleCount(const GLInfo& info) { if (samples > maxSampleCnt) { break; } - configMap[config].colorSampleCounts.push_back(samples); + pixelFormatMap[pixelFormat].colorSampleCounts.push_back(samples); } } } diff --git a/tgfx/src/gpu/opengl/GLCaps.h b/tgfx/src/gpu/opengl/GLCaps.h index 5c35bfa0ca..c2b3af809e 100644 --- a/tgfx/src/gpu/opengl/GLCaps.h +++ b/tgfx/src/gpu/opengl/GLCaps.h @@ -26,7 +26,7 @@ #include "core/utils/EnumHasher.h" #include "core/utils/Log.h" #include "gpu/Caps.h" -#include "gpu/PixelConfig.h" +#include "gpu/PixelFormat.h" #include "gpu/Swizzle.h" #define GL_VER(major, minor) ((static_cast(major) << 16) | static_cast(minor)) @@ -130,15 +130,15 @@ class GLCaps : public Caps { explicit GLCaps(const GLInfo& info); - const TextureFormat& getTextureFormat(PixelConfig config) const; + const TextureFormat& getTextureFormat(PixelFormat pixelFormat) const; - const Swizzle& configSwizzle(PixelConfig config) const; + const Swizzle& getSwizzle(PixelFormat pixelFormat) const; - const Swizzle& configTextureSwizzle(PixelConfig config) const; + const Swizzle& getTextureSwizzle(PixelFormat pixelFormat) const; - const Swizzle& configOutputSwizzle(PixelConfig config) const; + const Swizzle& getOutputSwizzle(PixelFormat pixelFormat) const; - int getSampleCount(int requestedCount, PixelConfig config) const; + int getSampleCount(int requestedCount, PixelFormat pixelFormat) const; /** * Does the preferred MSAA FBO extension have MSAA renderBuffers? @@ -152,9 +152,9 @@ class GLCaps : public Caps { bool usesImplicitMSAAResolve() const; private: - std::unordered_map configMap = {}; + std::unordered_map pixelFormatMap = {}; - void initConfigMap(const GLInfo& info); + void initFormatMap(const GLInfo& info); void initColorSampleCount(const GLInfo& info); void initGLSupport(const GLInfo& info); void initGLESSupport(const GLInfo& info); diff --git a/tgfx/src/gpu/opengl/GLDefines.h b/tgfx/src/gpu/opengl/GLDefines.h index 7c36b71ccb..57018f74a0 100644 --- a/tgfx/src/gpu/opengl/GLDefines.h +++ b/tgfx/src/gpu/opengl/GLDefines.h @@ -24,6 +24,7 @@ namespace GL { #undef FALSE #undef TRUE + // The following constants consist of the intersection of GL constants // exported by GLES 1.0, GLES 2.0, and desktop GL required by the system. diff --git a/tgfx/src/gpu/opengl/GLDrawer.cpp b/tgfx/src/gpu/opengl/GLDrawer.cpp index 8280ca73c4..71db429ca3 100644 --- a/tgfx/src/gpu/opengl/GLDrawer.cpp +++ b/tgfx/src/gpu/opengl/GLDrawer.cpp @@ -121,24 +121,25 @@ static std::shared_ptr CreateDstTexture(const DrawArgs& args, Point* ds return nullptr; } GLStateGuard stateGuard(args.context); - gl->bindFramebuffer(GL::FRAMEBUFFER, args.renderTarget->getGLInfo().id); - auto textureInfo = std::static_pointer_cast(dstTexture)->getGLInfo(); - gl->bindTexture(textureInfo.target, textureInfo.id); + auto renderTarget = static_cast(args.renderTarget); + gl->bindFramebuffer(GL::FRAMEBUFFER, renderTarget->glFrameBuffer().id); + auto glSampler = std::static_pointer_cast(dstTexture)->glSampler(); + gl->bindTexture(glSampler.target, glSampler.id); // format != BGRA && !srcHasMSAARenderBuffer && !dstHasMSAARenderBuffer && dstIsTextureable && // dstOrigin == srcOrigin && canConfigBeFBOColorAttachment(srcConfig) && (!srcIsTextureable || // srcIsGLTexture2D) - gl->copyTexSubImage2D(textureInfo.target, 0, 0, 0, static_cast(dstRect.x()), + gl->copyTexSubImage2D(glSampler.target, 0, 0, 0, static_cast(dstRect.x()), static_cast(dstRect.y()), static_cast(dstRect.width()), static_cast(dstRect.height())); - gl->bindTexture(textureInfo.target, 0); + gl->bindTexture(glSampler.target, 0); return dstTexture; } -static PixelConfig GetOutputPixelConfig(const DrawArgs& args) { +static PixelFormat GetOutputPixelFormat(const DrawArgs& args) { if (args.renderTargetTexture) { - return args.renderTargetTexture->getSampler()->config; + return args.renderTargetTexture->getSampler()->format; } - return PixelConfig::RGBA_8888; + return PixelFormat::RGBA_8888; } static void UpdateScissor(const GLInterface* gl, const DrawArgs& args) { @@ -188,8 +189,8 @@ void GLDrawer::draw(DrawArgs args, std::unique_ptr op) const { dstTexture = CreateDstTexture(args, &dstTextureOffset); } } - auto config = GetOutputPixelConfig(args); - const auto& swizzle = gl->caps->configOutputSwizzle(config); + auto config = GetOutputPixelFormat(args); + const auto& swizzle = gl->caps->getOutputSwizzle(config); Pipeline pipeline(std::move(fragmentProcessors), numColorProcessors, std::move(xferProcessor), dstTexture, dstTextureOffset, &swizzle); GLStateGuard stateGuard(args.context); @@ -200,9 +201,10 @@ void GLDrawer::draw(DrawArgs args, std::unique_ptr op) const { return; } CheckGLError(gl); + auto renderTarget = static_cast(args.renderTarget); gl->useProgram(program->programID()); - gl->bindFramebuffer(GL::FRAMEBUFFER, args.renderTarget->getGLInfo().id); - gl->viewport(0, 0, args.renderTarget->width(), args.renderTarget->height()); + gl->bindFramebuffer(GL::FRAMEBUFFER, renderTarget->glFrameBuffer().id); + gl->viewport(0, 0, renderTarget->width(), renderTarget->height()); UpdateScissor(gl, args); UpdateBlend(gl, blendAsCoeff, first, second); if (pipeline.needsBarrierTexture(args.renderTargetTexture.get())) { diff --git a/tgfx/src/gpu/opengl/GLDrawer.h b/tgfx/src/gpu/opengl/GLDrawer.h index 908aa0628e..3a36e43e35 100644 --- a/tgfx/src/gpu/opengl/GLDrawer.h +++ b/tgfx/src/gpu/opengl/GLDrawer.h @@ -19,18 +19,19 @@ #pragma once #include "GLBuffer.h" -#include "GLRenderTarget.h" +#include "GLContext.h" #include "core/BlendMode.h" #include "gpu/AAType.h" #include "gpu/FragmentProcessor.h" #include "gpu/GeometryProcessor.h" +#include "gpu/opengl/GLRenderTarget.h" namespace tgfx { struct DrawArgs { Context* context = nullptr; BlendMode blendMode = BlendMode::SrcOver; Matrix viewMatrix = Matrix::I(); - const GLRenderTarget* renderTarget = nullptr; + const RenderTarget* renderTarget = nullptr; std::shared_ptr renderTargetTexture = nullptr; Rect rectToDraw = Rect::MakeEmpty(); Rect scissorRect = Rect::MakeEmpty(); diff --git a/tgfx/src/gpu/opengl/GLProgram.cpp b/tgfx/src/gpu/opengl/GLProgram.cpp index 48d607bfd4..89c9984fa2 100644 --- a/tgfx/src/gpu/opengl/GLProgram.cpp +++ b/tgfx/src/gpu/opengl/GLProgram.cpp @@ -18,9 +18,9 @@ #include "GLProgram.h" #include "GLContext.h" -#include "GLTexture.h" #include "GLUtil.h" #include "gpu/Pipeline.h" +#include "gpu/opengl/GLTexture.h" namespace tgfx { GLProgram::GLProgram(unsigned programID, const std::vector& uniforms, @@ -60,8 +60,8 @@ void GLProgram::onRelease(Context* context) { } static void BindGLTexture(const GLInterface* gl, int position, const TextureSampler* sampler) { - const auto& glInfo = static_cast(sampler)->glInfo; - ActiveGLTexture(gl, GL::TEXTURE0 + position, glInfo.target, glInfo.id, sampler->config); + auto glSampler = static_cast(sampler); + ActiveGLTexture(gl, GL::TEXTURE0 + position, glSampler->target, glSampler->id, glSampler->format); } void GLProgram::updateUniformsAndTextureBindings(const GLInterface* gl, diff --git a/tgfx/src/gpu/opengl/GLRenderTarget.cpp b/tgfx/src/gpu/opengl/GLRenderTarget.cpp index 5d993cda27..da81de7c45 100644 --- a/tgfx/src/gpu/opengl/GLRenderTarget.cpp +++ b/tgfx/src/gpu/opengl/GLRenderTarget.cpp @@ -16,28 +16,42 @@ // ///////////////////////////////////////////////////////////////////////////////////////////////// -#include "GLRenderTarget.h" -#include "GLContext.h" -#include "GLState.h" -#include "GLUtil.h" +#include "gpu/opengl/GLRenderTarget.h" #include "core/Bitmap.h" +#include "gpu/opengl/GLContext.h" +#include "gpu/opengl/GLState.h" +#include "gpu/opengl/GLUtil.h" namespace tgfx { std::shared_ptr GLRenderTarget::MakeFrom(Context* context, - const BackendRenderTarget& renderTarget, - ImageOrigin origin) { - GLFrameBufferInfo glInfo = {}; - if (context == nullptr || !renderTarget.getGLFramebufferInfo(&glInfo)) { + const GLFrameBuffer& frameBuffer, + int width, int height, ImageOrigin origin, + int sampleCount) { + if (context == nullptr || width <= 0 || height <= 0) { + return nullptr; + } + auto target = new GLRenderTarget(width, height, origin, sampleCount, frameBuffer); + target->renderTargetFBInfo = frameBuffer; + target->externalTexture = true; + return Resource::Wrap(context, target); +} + +std::shared_ptr GLRenderTarget::MakeAdopted(Context* context, + const GLFrameBuffer& frameBuffer, + int width, int height, + ImageOrigin origin, int sampleCount) { + if (context == nullptr || width <= 0 || height <= 0) { return nullptr; } - auto target = new GLRenderTarget(renderTarget.width(), renderTarget.height(), origin, glInfo); - target->renderTargetFBInfo = glInfo; + auto target = new GLRenderTarget(width, height, origin, sampleCount, frameBuffer); + target->renderTargetFBInfo = frameBuffer; return Resource::Wrap(context, target); } -static bool RenderbufferStorageMSAA(const GLInterface* gl, int sampleCount, unsigned format, +static bool RenderbufferStorageMSAA(const GLInterface* gl, int sampleCount, PixelFormat pixelFormat, int width, int height) { CheckGLError(gl); + auto format = gl->caps->getTextureFormat(pixelFormat).sizedFormat; switch (gl->caps->msFBOType) { case MSFBOType::Standard: gl->renderbufferStorageMultisample(GL::RENDERBUFFER, sampleCount, format, width, height); @@ -67,8 +81,8 @@ static void FrameBufferTexture2D(const GLInterface* gl, unsigned textureTarget, } } -static void ReleaseResource(Context* context, GLFrameBufferInfo* textureFBInfo, - GLFrameBufferInfo* renderTargetFBInfo = nullptr, +static void ReleaseResource(Context* context, GLFrameBuffer* textureFBInfo, + GLFrameBuffer* renderTargetFBInfo = nullptr, unsigned* msRenderBufferID = nullptr) { auto gl = GLContext::Unwrap(context); if (textureFBInfo && textureFBInfo->id) { @@ -93,8 +107,8 @@ static void ReleaseResource(Context* context, GLFrameBufferInfo* textureFBInfo, } } -static bool CreateRenderBuffer(const GLInterface* gl, GLTexture* texture, - GLFrameBufferInfo* renderTargetFBInfo, unsigned* msRenderBufferID, +static bool CreateRenderBuffer(const GLInterface* gl, const GLTexture* texture, + GLFrameBuffer* renderTargetFBInfo, unsigned* msRenderBufferID, int sampleCount) { gl->genFramebuffers(1, &(renderTargetFBInfo->id)); if (renderTargetFBInfo->id == 0) { @@ -115,21 +129,21 @@ static bool CreateRenderBuffer(const GLInterface* gl, GLTexture* texture, return gl->checkFramebufferStatus(GL::FRAMEBUFFER) == GL::FRAMEBUFFER_COMPLETE; } -std::shared_ptr GLRenderTarget::MakeFrom(Context* context, GLTexture* texture, +std::shared_ptr GLRenderTarget::MakeFrom(Context* context, const GLTexture* texture, int sampleCount) { if (texture == nullptr || context == nullptr) { return nullptr; } auto gl = GLContext::Unwrap(context); - GLFrameBufferInfo textureFBInfo = {}; - textureFBInfo.format = texture->getGLInfo().format; + GLFrameBuffer textureFBInfo = {}; + textureFBInfo.format = texture->glSampler().format; gl->genFramebuffers(1, &textureFBInfo.id); if (textureFBInfo.id == 0) { return nullptr; } GLStateGuard stateGuard(context); - GLFrameBufferInfo renderTargetFBInfo = {}; - renderTargetFBInfo.format = texture->getGLInfo().format; + GLFrameBuffer renderTargetFBInfo = {}; + renderTargetFBInfo.format = texture->glSampler().format; unsigned msRenderBufferID = 0; if (sampleCount > 1 && gl->caps->usesMSAARenderBuffers()) { if (!CreateRenderBuffer(gl, texture, &renderTargetFBInfo, &msRenderBufferID, sampleCount)) { @@ -140,17 +154,16 @@ std::shared_ptr GLRenderTarget::MakeFrom(Context* context, GLTex renderTargetFBInfo = textureFBInfo; } gl->bindFramebuffer(GL::FRAMEBUFFER, textureFBInfo.id); - auto textureInfo = texture->getGLInfo(); + auto textureInfo = texture->glSampler(); FrameBufferTexture2D(gl, textureInfo.target, textureInfo.id, sampleCount); std::shared_ptr renderTarget = nullptr; if (gl->checkFramebufferStatus(GL::FRAMEBUFFER) != GL::FRAMEBUFFER_COMPLETE) { ReleaseResource(context, &textureFBInfo, &renderTargetFBInfo, &msRenderBufferID); } else { - auto textureTarget = texture->getGLInfo().target; + auto textureTarget = texture->glSampler().target; auto rt = new GLRenderTarget(texture->width(), texture->height(), texture->origin(), - textureFBInfo, textureTarget); - rt->_sampleCount = sampleCount; + sampleCount, textureFBInfo, textureTarget); rt->renderTargetFBInfo = renderTargetFBInfo; rt->msRenderBufferID = msRenderBufferID; renderTarget = Resource::Wrap(context, rt); @@ -158,12 +171,10 @@ std::shared_ptr GLRenderTarget::MakeFrom(Context* context, GLTex return renderTarget; } -GLRenderTarget::GLRenderTarget(int width, int height, ImageOrigin origin, GLFrameBufferInfo info, - unsigned int textureTarget) - : _width(width), - _height(height), - _origin(origin), - textureFBInfo(info), +GLRenderTarget::GLRenderTarget(int width, int height, ImageOrigin origin, int sampleCount, + GLFrameBuffer frameBuffer, unsigned textureTarget) + : RenderTarget(width, height, origin, sampleCount), + textureFBInfo(frameBuffer), textureTarget(textureTarget) { } @@ -171,8 +182,8 @@ void GLRenderTarget::clear(const GLInterface* gl) const { int oldFb = 0; gl->getIntegerv(GL::FRAMEBUFFER_BINDING, &oldFb); gl->bindFramebuffer(GL::FRAMEBUFFER, renderTargetFBInfo.id); - gl->viewport(0, 0, _width, _height); - gl->scissor(0, 0, _width, _height); + gl->viewport(0, 0, width(), height()); + gl->scissor(0, 0, width(), height()); gl->clearColor(0.0f, 0.0f, 0.0f, 0.0f); gl->clear(GL::COLOR_BUFFER_BIT | GL::STENCIL_BUFFER_BIT | GL::DEPTH_BUFFER_BIT); gl->bindFramebuffer(GL::FRAMEBUFFER, oldFb); @@ -214,22 +225,21 @@ static void CopyPixels(const ImageInfo& srcInfo, const void* srcPixels, const Im bool GLRenderTarget::readPixels(Context* context, const ImageInfo& dstInfo, void* dstPixels, int srcX, int srcY) const { dstPixels = dstInfo.computeOffset(dstPixels, -srcX, -srcY); - auto outInfo = dstInfo.makeIntersect(-srcX, -srcY, _width, _height); + auto outInfo = dstInfo.makeIntersect(-srcX, -srcY, width(), height()); if (outInfo.isEmpty()) { return false; } - auto alphaOnly = renderTargetFBInfo.format == GL::R8; - auto pixelConfig = alphaOnly ? PixelConfig::ALPHA_8 : PixelConfig::RGBA_8888; + auto pixelFormat = renderTargetFBInfo.format; GLStateGuard stateGuard(context); auto gl = GLContext::Unwrap(context); - const auto& format = gl->caps->getTextureFormat(pixelConfig); + const auto& format = gl->caps->getTextureFormat(pixelFormat); gl->bindFramebuffer(GL::FRAMEBUFFER, renderTargetFBInfo.id); - auto colorType = alphaOnly ? ColorType::ALPHA_8 : ColorType::RGBA_8888; + auto colorType = pixelFormat == PixelFormat::ALPHA_8 ? ColorType::ALPHA_8 : ColorType::RGBA_8888; auto srcInfo = ImageInfo::Make(outInfo.width(), outInfo.height(), colorType, AlphaType::Premultiplied); void* pixels = nullptr; uint8_t* tempPixels = nullptr; - if (CanReadDirectly(gl, _origin, srcInfo, outInfo)) { + if (CanReadDirectly(gl, origin(), srcInfo, outInfo)) { pixels = dstPixels; if (outInfo.rowBytes() != outInfo.minRowBytes()) { gl->pixelStorei(GL::PACK_ROW_LENGTH, @@ -239,13 +249,13 @@ bool GLRenderTarget::readPixels(Context* context, const ImageInfo& dstInfo, void tempPixels = new uint8_t[srcInfo.byteSize()]; pixels = tempPixels; } - auto alignment = alphaOnly ? 1 : 4; + auto alignment = pixelFormat == PixelFormat::ALPHA_8 ? 1 : 4; gl->pixelStorei(GL::PACK_ALIGNMENT, alignment); - auto flipY = _origin == ImageOrigin::BottomLeft; + auto flipY = origin() == ImageOrigin::BottomLeft; auto readX = std::max(0, srcX); auto readY = std::max(0, srcY); if (flipY) { - readY = _height - readY - outInfo.height(); + readY = height() - readY - outInfo.height(); } gl->readPixels(readX, readY, outInfo.width(), outInfo.height(), format.externalFormat, GL::UNSIGNED_BYTE, pixels); @@ -257,7 +267,7 @@ bool GLRenderTarget::readPixels(Context* context, const ImageInfo& dstInfo, void } void GLRenderTarget::resolve(Context* context) const { - if (_sampleCount <= 1) { + if (sampleCount() <= 1) { return; } auto gl = GLContext::Unwrap(context); @@ -270,28 +280,28 @@ void GLRenderTarget::resolve(Context* context) const { if (gl->caps->msFBOType == MSFBOType::ES_Apple) { // Apple's extension uses the scissor as the blit bounds. gl->enable(GL::SCISSOR_TEST); - gl->scissor(0, 0, _width, _height); + gl->scissor(0, 0, width(), height()); gl->resolveMultisampleFramebuffer(); gl->disable(GL::SCISSOR_TEST); } else { // BlitFrameBuffer respects the scissor, so disable it. gl->disable(GL::SCISSOR_TEST); - gl->blitFramebuffer(0, 0, _width, _height, 0, 0, _width, _height, GL::COLOR_BUFFER_BIT, + gl->blitFramebuffer(0, 0, width(), height(), 0, 0, width(), height(), GL::COLOR_BUFFER_BIT, GL::NEAREST); } } void GLRenderTarget::onRelease(Context* context) { - if (textureTarget == 0) { + if (externalTexture) { return; } - { + if (textureTarget != 0) { // The currently bound fboID may be the same as textureFBInfo.id, we must restore and then // delete, otherwise GL::INVALID_OPERATION(1282) will be reported。 GLStateGuard stateGuard(context); auto gl = GLContext::Unwrap(context); gl->bindFramebuffer(GL::FRAMEBUFFER, textureFBInfo.id); - FrameBufferTexture2D(gl, textureTarget, 0, _sampleCount); + FrameBufferTexture2D(gl, textureTarget, 0, sampleCount()); } ReleaseResource(context, &textureFBInfo, &renderTargetFBInfo, &msRenderBufferID); } diff --git a/tgfx/src/gpu/opengl/GLTextureSampler.cpp b/tgfx/src/gpu/opengl/GLSampler.cpp similarity index 81% rename from tgfx/src/gpu/opengl/GLTextureSampler.cpp rename to tgfx/src/gpu/opengl/GLSampler.cpp index 9c6cdec5b2..cfe2ca5cf6 100644 --- a/tgfx/src/gpu/opengl/GLTextureSampler.cpp +++ b/tgfx/src/gpu/opengl/GLSampler.cpp @@ -16,13 +16,13 @@ // ///////////////////////////////////////////////////////////////////////////////////////////////// -#include "GLTextureSampler.h" +#include "gpu/opengl/GLSampler.h" #include "GLContext.h" namespace tgfx { -void GLTextureSampler::computeKey(Context* context, BytesKey* bytesKey) const { +void GLSampler::computeKey(Context* context, BytesKey* bytesKey) const { const auto* gl = GLContext::Unwrap(context); - bytesKey->write(static_cast(gl->caps->configTextureSwizzle(config).asKey())); - bytesKey->write(glInfo.target); + bytesKey->write(static_cast(gl->caps->getTextureSwizzle(format).asKey())); + bytesKey->write(target); } } // namespace tgfx \ No newline at end of file diff --git a/tgfx/src/gpu/opengl/GLSurface.cpp b/tgfx/src/gpu/opengl/GLSurface.cpp index 268aa956c1..d28d8c2b6d 100644 --- a/tgfx/src/gpu/opengl/GLSurface.cpp +++ b/tgfx/src/gpu/opengl/GLSurface.cpp @@ -19,70 +19,58 @@ #include "GLSurface.h" #include "GLCaps.h" #include "GLContext.h" -#include "GLUtil.h" +#include "gpu/opengl/GLSemaphore.h" namespace tgfx { std::shared_ptr Surface::MakeFrom(Context* context, - const BackendRenderTarget& renderTarget, - ImageOrigin origin) { - auto rt = GLRenderTarget::MakeFrom(context, renderTarget, origin); - return GLSurface::MakeFrom(context, std::move(rt)); + std::shared_ptr renderTarget) { + if (renderTarget == nullptr || context == nullptr) { + return nullptr; + } + auto glRT = std::static_pointer_cast(renderTarget); + return std::shared_ptr(new GLSurface(context, std::move(glRT))); } -std::shared_ptr Surface::MakeFrom(Context* context, const BackendTexture& backendTexture, - ImageOrigin origin) { - auto texture = - std::static_pointer_cast(Texture::MakeFrom(context, backendTexture, origin)); - return GLSurface::MakeFrom(context, std::move(texture)); +std::shared_ptr Surface::MakeFrom(Context* context, std::shared_ptr texture, + int sampleCount) { + if (texture == nullptr || texture->isYUV()) { + return nullptr; + } + auto glTexture = std::static_pointer_cast(texture); + auto renderTarget = GLRenderTarget::MakeFrom(context, glTexture.get(), sampleCount); + if (renderTarget == nullptr) { + return nullptr; + } + auto surface = new GLSurface(context, renderTarget, glTexture); + return std::shared_ptr(surface); } std::shared_ptr Surface::Make(Context* context, int width, int height, bool alphaOnly, int sampleCount) { - auto config = alphaOnly ? PixelConfig::ALPHA_8 : PixelConfig::RGBA_8888; + auto pixelFormat = alphaOnly ? PixelFormat::ALPHA_8 : PixelFormat::RGBA_8888; std::shared_ptr texture; if (alphaOnly) { if (GLContext::Unwrap(context)->caps->textureRedSupport) { - texture = GLTexture::MakeAlpha(context, width, height); + texture = std::static_pointer_cast(Texture::MakeAlpha(context, width, height)); } } else { - texture = GLTexture::MakeRGBA(context, width, height); + texture = std::static_pointer_cast(Texture::MakeRGBA(context, width, height)); } if (texture == nullptr) { return nullptr; } auto gl = GLContext::Unwrap(context); - sampleCount = gl->caps->getSampleCount(sampleCount, config); + sampleCount = gl->caps->getSampleCount(sampleCount, pixelFormat); auto renderTarget = GLRenderTarget::MakeFrom(context, texture.get(), sampleCount); if (renderTarget == nullptr) { return nullptr; } - // 对于内部创建的 RenderTarget 默认清屏。 auto surface = new GLSurface(context, renderTarget, texture); + // 对于内部创建的 RenderTarget 默认清屏。 surface->getCanvas()->clear(); return std::shared_ptr(surface); } -std::shared_ptr GLSurface::MakeFrom(Context* context, - std::shared_ptr renderTarget) { - if (renderTarget == nullptr || context == nullptr) { - return nullptr; - } - return std::shared_ptr(new GLSurface(context, std::move(renderTarget))); -} - -std::shared_ptr GLSurface::MakeFrom(Context* context, - std::shared_ptr texture) { - if (texture == nullptr) { - return nullptr; - } - auto renderTarget = GLRenderTarget::MakeFrom(context, texture.get()); - if (renderTarget == nullptr) { - return nullptr; - } - auto surface = new GLSurface(context, renderTarget, texture); - return std::shared_ptr(surface); -} - GLSurface::GLSurface(Context* context, std::shared_ptr renderTarget, std::shared_ptr texture) : Surface(context), renderTarget(std::move(renderTarget)), texture(std::move(texture)) { @@ -99,20 +87,21 @@ Canvas* GLSurface::getCanvas() { return canvas; } -bool GLSurface::wait(const BackendSemaphore& semaphore) { - if (semaphore.glSync() == nullptr) { +bool GLSurface::wait(const Semaphore* semaphore) { + auto glSync = static_cast(semaphore)->glSync; + if (glSync == nullptr) { return false; } const auto* gl = GLContext::Unwrap(getContext()); if (!gl->caps->semaphoreSupport) { return false; } - gl->waitSync(semaphore.glSync(), 0, GL::TIMEOUT_IGNORED); - gl->deleteSync(semaphore.glSync()); + gl->waitSync(glSync, 0, GL::TIMEOUT_IGNORED); + gl->deleteSync(glSync); return true; } -bool GLSurface::flush(BackendSemaphore* semaphore) { +bool GLSurface::flush(Semaphore* semaphore) { if (semaphore == nullptr) { if (canvas) { canvas->flush(); @@ -125,7 +114,7 @@ bool GLSurface::flush(BackendSemaphore* semaphore) { } auto* sync = gl->fenceSync(GL::SYNC_GPU_COMMANDS_COMPLETE, 0); if (sync) { - semaphore->initGL(sync); + static_cast(semaphore)->glSync = sync; // If we inserted semaphores during the flush, we need to call glFlush. gl->flush(); return true; @@ -133,10 +122,6 @@ bool GLSurface::flush(BackendSemaphore* semaphore) { return false; } -std::shared_ptr GLSurface::getRenderTarget() const { - return renderTarget; -} - std::shared_ptr GLSurface::getTexture() const { if (canvas) { canvas->flush(); diff --git a/tgfx/src/gpu/opengl/GLSurface.h b/tgfx/src/gpu/opengl/GLSurface.h index 2bb2d9ed22..ce0453c252 100644 --- a/tgfx/src/gpu/opengl/GLSurface.h +++ b/tgfx/src/gpu/opengl/GLSurface.h @@ -19,18 +19,13 @@ #pragma once #include "GLCanvas.h" -#include "GLRenderTarget.h" -#include "GLTexture.h" #include "gpu/Surface.h" +#include "gpu/opengl/GLRenderTarget.h" +#include "gpu/opengl/GLTexture.h" namespace tgfx { class GLSurface : public Surface { public: - static std::shared_ptr MakeFrom(Context* context, - std::shared_ptr renderTarget); - - static std::shared_ptr MakeFrom(Context* context, std::shared_ptr texture); - ~GLSurface() override; int width() const override { @@ -47,11 +42,13 @@ class GLSurface : public Surface { Canvas* getCanvas() override; - bool wait(const BackendSemaphore& semaphore) override; + bool wait(const Semaphore* semaphore) override; - bool flush(BackendSemaphore* semaphore) override; + bool flush(Semaphore* semaphore) override; - std::shared_ptr getRenderTarget() const; + std::shared_ptr getRenderTarget() const override { + return renderTarget; + } std::shared_ptr getTexture() const override; @@ -63,8 +60,8 @@ class GLSurface : public Surface { std::shared_ptr texture = nullptr; GLCanvas* canvas = nullptr; - GLSurface(Context* context, std::shared_ptr renderTarget, - std::shared_ptr texture = nullptr); + explicit GLSurface(Context* context, std::shared_ptr renderTarget, + std::shared_ptr texture = nullptr); friend class Surface; }; diff --git a/tgfx/src/gpu/opengl/GLTexture.cpp b/tgfx/src/gpu/opengl/GLTexture.cpp index e6e0e9cd0d..c4b94efd6b 100644 --- a/tgfx/src/gpu/opengl/GLTexture.cpp +++ b/tgfx/src/gpu/opengl/GLTexture.cpp @@ -16,17 +16,16 @@ // ///////////////////////////////////////////////////////////////////////////////////////////////// -#include "GLTexture.h" +#include "gpu/opengl/GLTexture.h" #include "GLUtil.h" -#include "core/Bitmap.h" #include "core/utils/UniqueID.h" -#include "gpu/Surface.h" namespace tgfx { class GLBackendTexture : public GLTexture { public: - GLBackendTexture(GLTextureSampler textureSampler, int width, int height, ImageOrigin origin) - : GLTexture(width, height, origin) { + GLBackendTexture(GLSampler textureSampler, int width, int height, ImageOrigin origin, + bool adopted) + : GLTexture(width, height, origin), adopted(adopted) { sampler = std::move(textureSampler); } @@ -35,19 +34,32 @@ class GLBackendTexture : public GLTexture { } protected: - void onRelease(Context*) override { + void onRelease(Context* context) override { + if (adopted) { + auto gl = GLContext::Unwrap(context); + gl->deleteTextures(1, &sampler.id); + } } + + private: + bool adopted = false; }; -std::shared_ptr Texture::MakeFrom(Context* context, const BackendTexture& backendTexture, - ImageOrigin origin) { - GLTextureInfo glTextureInfo = {}; - if (context == nullptr || !backendTexture.getGLTextureInfo(&glTextureInfo)) { +std::shared_ptr GLTexture::MakeFrom(Context* context, const GLSampler& sampler, + int width, int height, ImageOrigin origin) { + if (context == nullptr || width <= 0 || height <= 0 || sampler.id == 0) { return nullptr; } - auto sampler = GLTextureSampler(PixelConfig::RGBA_8888, glTextureInfo); - auto texture = - new GLBackendTexture(sampler, backendTexture.width(), backendTexture.height(), origin); + auto texture = new GLBackendTexture(sampler, width, height, origin, false); + return Resource::Wrap(context, texture); +} + +std::shared_ptr GLTexture::MakeAdopted(Context* context, const GLSampler& sampler, + int width, int height, ImageOrigin origin) { + if (context == nullptr || width <= 0 || height <= 0 || sampler.id == 0) { + return nullptr; + } + auto texture = new GLBackendTexture(sampler, width, height, origin, true); return Resource::Wrap(context, texture); } @@ -60,7 +72,7 @@ class GLAlphaTexture : public GLTexture { recycleKey->write(static_cast(height)); } - GLAlphaTexture(GLTextureSampler textureSampler, int width, int height, ImageOrigin origin) + GLAlphaTexture(GLSampler textureSampler, int width, int height, ImageOrigin origin) : GLTexture(width, height, origin) { sampler = std::move(textureSampler); } @@ -76,7 +88,7 @@ class GLAlphaTexture : public GLTexture { void onRelease(Context* context) override { auto gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &sampler.glInfo.id); + gl->deleteTextures(1, &sampler.id); } }; @@ -89,7 +101,7 @@ class GLRGBATexture : public GLTexture { recycleKey->write(static_cast(height)); } - GLRGBATexture(GLTextureSampler textureSampler, int width, int height, + GLRGBATexture(GLSampler textureSampler, int width, int height, ImageOrigin origin = ImageOrigin::TopLeft) : GLTexture(width, height, origin) { sampler = std::move(textureSampler); @@ -106,7 +118,7 @@ class GLRGBATexture : public GLTexture { void onRelease(Context* context) override { auto gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &sampler.glInfo.id); + gl->deleteTextures(1, &sampler.id); } }; @@ -125,8 +137,8 @@ std::shared_ptr Texture::Make(Context* context, int width, int height, if (!CheckMaxTextureSize(gl, width, height)) { return nullptr; } - PixelConfig pixelConfig = alphaOnly ? PixelConfig::ALPHA_8 : PixelConfig::RGBA_8888; - const auto& format = gl->caps->getTextureFormat(pixelConfig); + PixelFormat pixelFormat = alphaOnly ? PixelFormat::ALPHA_8 : PixelFormat::RGBA_8888; + const auto& format = gl->caps->getTextureFormat(pixelFormat); GLStateGuard stateGuard(context); BytesKey recycleKey = {}; if (alphaOnly) { @@ -137,31 +149,30 @@ std::shared_ptr Texture::Make(Context* context, int width, int height, auto texture = std::static_pointer_cast(context->resourceCache()->getRecycled(recycleKey)); - GLTextureInfo glInfo = {}; + GLSampler sampler = {}; if (texture) { texture->_origin = origin; - glInfo = texture->getGLInfo(); + sampler = texture->glSampler(); } else { - glInfo.target = GL::TEXTURE_2D; - glInfo.format = format.sizedFormat; - gl->genTextures(1, &(glInfo.id)); - if (glInfo.id == 0) { + sampler.target = GL::TEXTURE_2D; + sampler.format = pixelFormat; + gl->genTextures(1, &(sampler.id)); + if (sampler.id == 0) { return nullptr; } - gl->bindTexture(glInfo.target, glInfo.id); - gl->texParameteri(glInfo.target, GL::TEXTURE_WRAP_S, GL::CLAMP_TO_EDGE); - gl->texParameteri(glInfo.target, GL::TEXTURE_WRAP_T, GL::CLAMP_TO_EDGE); - gl->texParameteri(glInfo.target, GL::TEXTURE_MIN_FILTER, GL::LINEAR); - gl->texParameteri(glInfo.target, GL::TEXTURE_MAG_FILTER, GL::LINEAR); + gl->bindTexture(sampler.target, sampler.id); + gl->texParameteri(sampler.target, GL::TEXTURE_WRAP_S, GL::CLAMP_TO_EDGE); + 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); if (pixels == nullptr) { - gl->texImage2D(glInfo.target, 0, static_cast(format.internalFormatTexImage), width, + gl->texImage2D(sampler.target, 0, static_cast(format.internalFormatTexImage), width, height, 0, format.externalFormat, GL::UNSIGNED_BYTE, nullptr); } if (!CheckGLError(gl)) { - gl->deleteTextures(1, &glInfo.id); + gl->deleteTextures(1, &sampler.id); return nullptr; } - auto sampler = GLTextureSampler(pixelConfig, glInfo); if (alphaOnly) { texture = Resource::Wrap(context, new GLAlphaTexture(sampler, width, height, origin)); } else { @@ -170,7 +181,7 @@ std::shared_ptr Texture::Make(Context* context, int width, int height, } if (pixels != nullptr) { int bytesPerPixel = alphaOnly ? 1 : 4; - SubmitGLTexture(gl, glInfo, format, width, height, rowBytes, bytesPerPixel, pixels); + SubmitGLTexture(gl, sampler, width, height, rowBytes, bytesPerPixel, pixels); } return texture; } @@ -183,12 +194,6 @@ std::shared_ptr Texture::MakeAlpha(Context* context, int width, int hei return Make(context, width, height, pixels, rowBytes, origin, true); } -std::shared_ptr GLTexture::MakeAlpha(Context* context, int width, int height, - ImageOrigin origin) { - auto texture = Texture::MakeAlpha(context, width, height, nullptr, 0, origin); - return std::static_pointer_cast(texture); -} - std::shared_ptr Texture::MakeRGBA(Context* context, int width, int height, void* pixels, size_t rowBytes, ImageOrigin origin) { if (context == nullptr) { @@ -197,19 +202,6 @@ std::shared_ptr Texture::MakeRGBA(Context* context, int width, int heig return Make(context, width, height, pixels, rowBytes, origin, false); } -std::shared_ptr GLTexture::MakeRGBA(Context* context, int width, int height, - ImageOrigin origin) { - auto texture = Texture::MakeRGBA(context, width, height, nullptr, 0, origin); - return std::static_pointer_cast(texture); -} - -GLTextureInfo GLTexture::Unwrap(const Texture* texture) { - if (texture == nullptr || texture->isYUV()) { - return {}; - } - return static_cast(texture)->sampler.glInfo; -} - GLTexture::GLTexture(int width, int height, ImageOrigin origin) : Texture(width, height, origin) { } diff --git a/tgfx/src/gpu/opengl/GLUniformHandler.cpp b/tgfx/src/gpu/opengl/GLUniformHandler.cpp index 186984ff29..58e63bdf9e 100644 --- a/tgfx/src/gpu/opengl/GLUniformHandler.cpp +++ b/tgfx/src/gpu/opengl/GLUniformHandler.cpp @@ -18,7 +18,7 @@ #include "GLUniformHandler.h" #include "GLProgramBuilder.h" -#include "GLTexture.h" +#include "gpu/opengl/GLTexture.h" namespace tgfx { UniformHandle GLUniformHandler::internalAddUniform(ShaderFlags visibility, ShaderVar::Type type, @@ -46,10 +46,10 @@ SamplerHandle GLUniformHandler::addSampler(const TextureSampler* sampler, const auto mangleName = programBuilder->nameVariable('u', name); const auto* gl = static_cast(programBuilder)->gl(); - const auto& swizzle = gl->caps->configTextureSwizzle(sampler->config); + const auto& swizzle = gl->caps->getTextureSwizzle(sampler->format); ShaderVar::Type type; - switch (static_cast(sampler)->glInfo.target) { + switch (static_cast(sampler)->target) { case GL::TEXTURE_EXTERNAL_OES: programBuilder->fragmentShaderBuilder()->addFeature(PrivateFeature::OESTexture, "GL_OES_EGL_image_external"); diff --git a/tgfx/src/gpu/opengl/GLUtil.cpp b/tgfx/src/gpu/opengl/GLUtil.cpp index 0059027586..d3b0906eb3 100644 --- a/tgfx/src/gpu/opengl/GLUtil.cpp +++ b/tgfx/src/gpu/opengl/GLUtil.cpp @@ -50,9 +50,9 @@ GLVersion GetGLVersion(const char* versionString) { return {}; } -bool CreateGLTexture(const GLInterface* gl, int width, int height, GLTextureInfo* texture) { +bool CreateGLTexture(const GLInterface* gl, int width, int height, GLSampler* texture) { texture->target = GL::TEXTURE_2D; - texture->format = GL::RGBA8; + texture->format = PixelFormat::RGBA_8888; gl->genTextures(1, &texture->id); if (texture->id <= 0) { return false; @@ -95,7 +95,7 @@ static std::array GetGLSwizzleValues(const Swizzle& swizzle) { } void ActiveGLTexture(const GLInterface* gl, unsigned textureUnit, unsigned target, - unsigned textureID, PixelConfig pixelConfig) { + unsigned textureID, PixelFormat pixelFormat) { gl->activeTexture(textureUnit); gl->bindTexture(target, textureID); gl->texParameteri(target, GL::TEXTURE_WRAP_S, GL::CLAMP_TO_EDGE); @@ -103,7 +103,7 @@ void ActiveGLTexture(const GLInterface* gl, unsigned textureUnit, unsigned targe gl->texParameteri(target, GL::TEXTURE_MIN_FILTER, GL::LINEAR); gl->texParameteri(target, GL::TEXTURE_MAG_FILTER, GL::LINEAR); if (gl->caps->textureSwizzleSupport) { - const auto& swizzle = gl->caps->configSwizzle(pixelConfig); + const auto& swizzle = gl->caps->getSwizzle(pixelFormat); auto glValues = GetGLSwizzleValues(swizzle); if (gl->caps->standard == GLStandard::GL) { gl->texParameteriv(target, GL::TEXTURE_SWIZZLE_RGBA, @@ -118,34 +118,34 @@ void ActiveGLTexture(const GLInterface* gl, unsigned textureUnit, unsigned targe } } -void SubmitGLTexture(const GLInterface* gl, const GLTextureInfo& glInfo, - const TextureFormat& format, int width, int height, size_t rowBytes, - int bytesPerPixel, void* pixels) { +void SubmitGLTexture(const GLInterface* gl, const GLSampler& sampler, int width, int height, + size_t rowBytes, int bytesPerPixel, void* pixels) { if (pixels == nullptr || rowBytes == 0) { return; } - gl->bindTexture(glInfo.target, glInfo.id); + const auto& format = gl->caps->getTextureFormat(sampler.format); + gl->bindTexture(sampler.target, sampler.id); gl->pixelStorei(GL::UNPACK_ALIGNMENT, bytesPerPixel); if (gl->caps->unpackRowLengthSupport) { // the number of pixels, not bytes gl->pixelStorei(GL::UNPACK_ROW_LENGTH, static_cast(rowBytes / bytesPerPixel)); - gl->texImage2D(glInfo.target, 0, static_cast(format.internalFormatTexImage), width, height, - 0, format.externalFormat, GL::UNSIGNED_BYTE, pixels); + gl->texImage2D(sampler.target, 0, static_cast(format.internalFormatTexImage), width, + height, 0, format.externalFormat, GL::UNSIGNED_BYTE, pixels); } else { if (static_cast(width) * bytesPerPixel == rowBytes) { - gl->texImage2D(glInfo.target, 0, static_cast(format.internalFormatTexImage), width, + gl->texImage2D(sampler.target, 0, static_cast(format.internalFormatTexImage), width, height, 0, format.externalFormat, GL::UNSIGNED_BYTE, pixels); } else { - gl->texImage2D(glInfo.target, 0, static_cast(format.internalFormatTexImage), width, + gl->texImage2D(sampler.target, 0, static_cast(format.internalFormatTexImage), width, height, 0, format.externalFormat, GL::UNSIGNED_BYTE, nullptr); auto data = reinterpret_cast(pixels); for (int row = 0; row < height; ++row) { - gl->texSubImage2D(glInfo.target, 0, 0, row, width, 1, format.externalFormat, + gl->texSubImage2D(sampler.target, 0, 0, row, width, 1, format.externalFormat, GL::UNSIGNED_BYTE, data + (row * rowBytes)); } } } - gl->bindTexture(glInfo.target, 0); + gl->bindTexture(sampler.target, 0); } unsigned CreateGLProgram(const GLInterface* gl, const std::string& vertex, diff --git a/tgfx/src/gpu/opengl/GLUtil.h b/tgfx/src/gpu/opengl/GLUtil.h index b06b0c6fdf..c389aedbd3 100644 --- a/tgfx/src/gpu/opengl/GLUtil.h +++ b/tgfx/src/gpu/opengl/GLUtil.h @@ -24,6 +24,7 @@ #include "core/ImageOrigin.h" #include "core/Matrix.h" #include "gpu/opengl/GLContext.h" +#include "gpu/opengl/GLSampler.h" namespace tgfx { struct GLVersion { @@ -45,14 +46,13 @@ unsigned LoadGLShader(const GLInterface* gl, unsigned shaderType, const std::str bool CheckGLError(const GLInterface* gl); -bool CreateGLTexture(const GLInterface* gl, int width, int height, GLTextureInfo* texture); +bool CreateGLTexture(const GLInterface* gl, int width, int height, GLSampler* texture); void ActiveGLTexture(const GLInterface* gl, unsigned textureUnit, unsigned target, - unsigned textureID, PixelConfig pixelConfig = PixelConfig::RGBA_8888); + unsigned textureID, PixelFormat pixelFormat = PixelFormat::RGBA_8888); -void SubmitGLTexture(const GLInterface* gl, const GLTextureInfo& glInfo, - const TextureFormat& format, int width, int height, size_t rowBytes, - int bytesPerPixel, void* pixels); +void SubmitGLTexture(const GLInterface* gl, const GLSampler& sampler, int width, int height, + size_t rowBytes, int bytesPerPixel, void* pixels); std::array ToGLMatrix(const Matrix& matrix); std::array ToGLVertexMatrix(const Matrix& matrix, int width, int height, diff --git a/tgfx/src/gpu/opengl/GLYUVTexture.cpp b/tgfx/src/gpu/opengl/GLYUVTexture.cpp index ba85148d0a..fdf7c3915c 100644 --- a/tgfx/src/gpu/opengl/GLYUVTexture.cpp +++ b/tgfx/src/gpu/opengl/GLYUVTexture.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////////////////////// -#include "GLYUVTexture.h" +#include "gpu/opengl/GLYUVTexture.h" #include "GLUtil.h" #include "core/utils/UniqueID.h" @@ -42,7 +42,7 @@ struct YUVConfig { uint8_t* pixelsPlane[3]{}; int rowBytes[3]{}; int bytesPerPixel[3]{}; - TextureFormat formats[3]{}; + PixelFormat formats[3]{}; int planeCount = 0; }; @@ -98,36 +98,34 @@ class GLNV12Texture : public GLYUVTexture { } }; -static std::vector MakeTexturePlanes(const GLInterface* gl, - const YUVConfig& yuvConfig) { - std::vector texturePlanes{}; +static std::vector MakeTexturePlanes(const GLInterface* gl, const YUVConfig& yuvConfig) { + std::vector texturePlanes{}; unsigned yuvTextureIDs[] = {0, 0, 0}; gl->genTextures(yuvConfig.planeCount, yuvTextureIDs); if (yuvTextureIDs[0] == 0) { return texturePlanes; } for (int index = 0; index < yuvConfig.planeCount; index++) { - GLTextureInfo glInfo = {}; - glInfo.id = yuvTextureIDs[index]; - glInfo.target = GL::TEXTURE_2D; - glInfo.format = yuvConfig.formats[index].sizedFormat; - texturePlanes.emplace_back(glInfo); + GLSampler sampler = {}; + sampler.id = yuvTextureIDs[index]; + sampler.target = GL::TEXTURE_2D; + sampler.format = yuvConfig.formats[index]; + texturePlanes.emplace_back(sampler); } return texturePlanes; } static void SubmitYUVTexture(const GLInterface* gl, const YUVConfig& yuvConfig, - GLTextureSampler yuvTextures[]) { + const GLSampler yuvTextures[]) { static constexpr int factor[] = {0, 1, 1}; for (int index = 0; index < yuvConfig.planeCount; index++) { - auto glInfo = yuvTextures[index].glInfo; - auto format = yuvConfig.formats[index]; + const auto& sampler = yuvTextures[index]; auto w = yuvConfig.width >> factor[index]; auto h = yuvConfig.height >> factor[index]; auto rowBytes = yuvConfig.rowBytes[index]; auto bytesPerPixel = yuvConfig.bytesPerPixel[index]; auto pixels = yuvConfig.pixelsPlane[index]; - SubmitGLTexture(gl, glInfo, format, w, h, rowBytes, bytesPerPixel, pixels); + SubmitGLTexture(gl, sampler, w, h, rowBytes, bytesPerPixel, pixels); } } @@ -138,12 +136,10 @@ std::shared_ptr YUVTexture::MakeI420(Context* context, YUVColorSpace GLStateGuard stateGuard(context); YUVConfig yuvConfig = YUVConfig(colorSpace, colorRange, width, height, I420_PLANE_COUNT); - auto pixelConfig = PixelConfig::Gray_8; - const auto& format = gl->caps->getTextureFormat(pixelConfig); for (int i = 0; i < 3; i++) { yuvConfig.pixelsPlane[i] = pixelsPlane[i]; yuvConfig.rowBytes[i] = lineSize[i]; - yuvConfig.formats[i] = format; + yuvConfig.formats[i] = PixelFormat::GRAY_8; yuvConfig.bytesPerPixel[i] = 1; } @@ -159,9 +155,7 @@ std::shared_ptr YUVTexture::MakeI420(Context* context, YUVColorSpace texture = std::static_pointer_cast( Resource::Wrap(context, new GLI420Texture(yuvConfig.colorSpace, yuvConfig.colorRange, yuvConfig.width, yuvConfig.height))); - texture->samplers.emplace_back(pixelConfig, texturePlanes[0]); - texture->samplers.emplace_back(pixelConfig, texturePlanes[1]); - texture->samplers.emplace_back(pixelConfig, texturePlanes[2]); + texture->samplers = texturePlanes; } SubmitYUVTexture(gl, yuvConfig, &texture->samplers[0]); return texture; @@ -174,12 +168,12 @@ std::shared_ptr YUVTexture::MakeNV12(Context* context, YUVColorSpace GLStateGuard stateGuard(context); YUVConfig yuvConfig = YUVConfig(colorSpace, colorRange, width, height, NV12_PLANE_COUNT); - PixelConfig pixelConfig[2] = {PixelConfig::Gray_8, PixelConfig::RG_88}; for (int i = 0; i < 2; i++) { yuvConfig.pixelsPlane[i] = pixelsPlane[i]; yuvConfig.rowBytes[i] = lineSize[i]; - yuvConfig.formats[i] = gl->caps->getTextureFormat(pixelConfig[i]); } + yuvConfig.formats[0] = PixelFormat::GRAY_8; + yuvConfig.formats[1] = PixelFormat::RG_88; yuvConfig.bytesPerPixel[0] = 1; yuvConfig.bytesPerPixel[1] = 2; @@ -195,8 +189,7 @@ std::shared_ptr YUVTexture::MakeNV12(Context* context, YUVColorSpace texture = std::static_pointer_cast( Resource::Wrap(context, new GLNV12Texture(yuvConfig.colorSpace, yuvConfig.colorRange, yuvConfig.width, yuvConfig.height))); - texture->samplers.emplace_back(pixelConfig[0], texturePlanes[0]); - texture->samplers.emplace_back(pixelConfig[1], texturePlanes[1]); + texture->samplers = texturePlanes; } SubmitYUVTexture(gl, yuvConfig, &texture->samplers[0]); return texture; @@ -221,7 +214,7 @@ const TextureSampler* GLYUVTexture::getSamplerAt(size_t index) const { void GLYUVTexture::onRelease(Context* context) { auto gl = GLContext::Unwrap(context); for (const auto& sampler : samplers) { - gl->deleteTextures(1, &sampler.glInfo.id); + gl->deleteTextures(1, &sampler.id); } } } // namespace tgfx diff --git a/tgfx/src/gpu/opengl/cgl/CGLDevice.mm b/tgfx/src/gpu/opengl/cgl/CGLDevice.mm index b90b859d9e..1247f74e02 100644 --- a/tgfx/src/gpu/opengl/cgl/CGLDevice.mm +++ b/tgfx/src/gpu/opengl/cgl/CGLDevice.mm @@ -17,8 +17,6 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include "gpu/opengl/cgl/CGLDevice.h" -#include "CGLProcGetter.h" -#include "gpu/opengl/GLContext.h" namespace tgfx { void* GLDevice::CurrentNativeHandle() { diff --git a/tgfx/src/gpu/opengl/cgl/CGLHardwareTexture.mm b/tgfx/src/gpu/opengl/cgl/CGLHardwareTexture.mm index c9d57f88ff..9c82becd20 100644 --- a/tgfx/src/gpu/opengl/cgl/CGLHardwareTexture.mm +++ b/tgfx/src/gpu/opengl/cgl/CGLHardwareTexture.mm @@ -17,16 +17,17 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include "CGLHardwareTexture.h" -#include "gpu/opengl/cgl/CGLDevice.h" +#include #include "core/utils/UniqueID.h" +#include "gpu/opengl/cgl/CGLDevice.h" namespace tgfx { std::shared_ptr CGLHardwareTexture::MakeFrom(Context* context, CVPixelBufferRef pixelBuffer) { BytesKey recycleKey = {}; ComputeRecycleKey(&recycleKey, pixelBuffer); - auto glTexture = - std::static_pointer_cast(context->resourceCache()->getRecycled(recycleKey)); + auto glTexture = std::static_pointer_cast( + context->resourceCache()->getRecycled(recycleKey)); if (glTexture) { return glTexture; } @@ -44,16 +45,15 @@ if (texture == nil) { return nullptr; } - GLTextureInfo glInfo = {}; - glInfo.target = CVOpenGLTextureGetTarget(texture); - glInfo.id = CVOpenGLTextureGetName(texture); - auto oneComponent8 = - CVPixelBufferGetPixelFormatType(pixelBuffer) == kCVPixelFormatType_OneComponent8; - // mac 端创建的单通道纹理都是 GL::RED。 - glInfo.format = oneComponent8 ? GL::R8 : GL::RGBA8; + GLSampler glSampler = {}; + glSampler.target = CVOpenGLTextureGetTarget(texture); + glSampler.id = CVOpenGLTextureGetName(texture); + glSampler.format = + CVPixelBufferGetPixelFormatType(pixelBuffer) == kCVPixelFormatType_OneComponent8 + ? PixelFormat::ALPHA_8 + : PixelFormat::RGBA_8888; glTexture = Resource::Wrap(context, new CGLHardwareTexture(pixelBuffer)); - glTexture->sampler.glInfo = glInfo; - glTexture->sampler.config = oneComponent8 ? PixelConfig::ALPHA_8 : PixelConfig::RGBA_8888; + glTexture->sampler = glSampler; glTexture->texture = texture; return glTexture; } @@ -82,7 +82,7 @@ } Point CGLHardwareTexture::getTextureCoord(float x, float y) const { - if (sampler.glInfo.target == GL::TEXTURE_RECTANGLE) { + if (sampler.target == GL_TEXTURE_RECTANGLE) { return {x, y}; } return GLTexture::getTextureCoord(x, y); diff --git a/tgfx/src/gpu/opengl/cgl/CGLWindow.mm b/tgfx/src/gpu/opengl/cgl/CGLWindow.mm index 0e2378b133..4093f24f00 100644 --- a/tgfx/src/gpu/opengl/cgl/CGLWindow.mm +++ b/tgfx/src/gpu/opengl/cgl/CGLWindow.mm @@ -17,9 +17,10 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include "gpu/opengl/cgl/CGLWindow.h" +#include #include #include "CGLHardwareTexture.h" -#include "gpu/opengl/GLSurface.h" +#include "gpu/opengl/GLRenderTarget.h" namespace tgfx { static std::mutex threadCacheLocker = {}; @@ -106,23 +107,22 @@ #pragma clang diagnostic ignored "-Wdeprecated-declarations" [glContext setView:view]; #pragma clang diagnostic pop - GLFrameBufferInfo glInfo = {}; - glInfo.id = 0; - glInfo.format = GL::RGBA8; - BackendRenderTarget renderTarget(glInfo, size.width, size.height); - return Surface::MakeFrom(context, renderTarget, ImageOrigin::BottomLeft); + GLFrameBuffer frameBuffer = {}; + frameBuffer.id = 0; + frameBuffer.format = PixelFormat::RGBA_8888; + auto renderTarget = GLRenderTarget::MakeFrom(context, frameBuffer, size.width, size.height, ImageOrigin::BottomLeft); + return Surface::MakeFrom(context, renderTarget); } auto texture = CGLHardwareTexture::MakeFrom(context, pixelBuffer); - return GLSurface::MakeFrom(context, texture); + return Surface::MakeFrom(context, texture); } -void CGLWindow::onPresent(Context* context, int64_t) { +void CGLWindow::onPresent(Context*, int64_t) { auto glContext = static_cast(device.get())->glContext; if (view) { [glContext flushBuffer]; } else { - auto gl = GLContext::Unwrap(context); - gl->flush(); + glFlush(); } } } // namespace tgfx diff --git a/tgfx/src/gpu/opengl/eagl/EAGLHardwareTexture.mm b/tgfx/src/gpu/opengl/eagl/EAGLHardwareTexture.mm index b5fea6d984..d5c34a1321 100644 --- a/tgfx/src/gpu/opengl/eagl/EAGLHardwareTexture.mm +++ b/tgfx/src/gpu/opengl/eagl/EAGLHardwareTexture.mm @@ -19,31 +19,28 @@ #include "EAGLHardwareTexture.h" #include "gpu/opengl/eagl/EAGLDevice.h" #include "core/utils/UniqueID.h" +#include "gpu/opengl/GLContext.h" namespace tgfx { static CVOpenGLESTextureRef GetTextureRef(Context* context, CVPixelBufferRef pixelBuffer, - CVOpenGLESTextureCacheRef textureCache, - unsigned* sizedFormat) { + CVOpenGLESTextureCacheRef textureCache) { if (textureCache == nil) { return nil; } auto width = static_cast(CVPixelBufferGetWidth(pixelBuffer)); auto height = static_cast(CVPixelBufferGetHeight(pixelBuffer)); - auto pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer); CVOpenGLESTextureRef texture = nil; CVReturn result; - if (pixelFormat == kCVPixelFormatType_OneComponent8) { - auto gl = GLContext::Unwrap(context); - const auto& format = gl->caps->getTextureFormat(PixelConfig::ALPHA_8); - *sizedFormat = format.sizedFormat; + if (CVPixelBufferGetPixelFormatType(pixelBuffer) == kCVPixelFormatType_OneComponent8) { + auto gl = GLContext::Unwrap(context); + const auto& format = gl->caps->getTextureFormat(PixelFormat::ALPHA_8); // 返回的 texture 对象是一个强引用计数为 1 的对象。 result = CVOpenGLESTextureCacheCreateTextureFromImage( kCFAllocatorDefault, textureCache, pixelBuffer, NULL, /* texture attributes */ GL::TEXTURE_2D, format.internalFormatTexImage, /* opengl format */ - width, height, format.externalFormat, /* native iOS format */ + width, height, GL::RED, /* native iOS format */ GL::UNSIGNED_BYTE, 0, &texture); } else { - *sizedFormat = GL::RGBA8; // 返回的 texture 对象是一个强引用计数为 1 的对象。 result = CVOpenGLESTextureCacheCreateTextureFromImage( kCFAllocatorDefault, textureCache, pixelBuffer, NULL, /* texture attributes */ @@ -72,20 +69,19 @@ static CVOpenGLESTextureRef GetTextureRef(Context* context, CVPixelBufferRef pix if (eaglDevice == nullptr) { return nullptr; } - unsigned sizedFormat = 0; - auto texture = GetTextureRef(context, pixelBuffer, eaglDevice->getTextureCache(), &sizedFormat); + + auto texture = GetTextureRef(context, pixelBuffer, eaglDevice->getTextureCache()); if (texture == nil) { return nullptr; } - GLTextureInfo glInfo = {}; + GLSampler glInfo = {}; + auto oneComponent8 = + CVPixelBufferGetPixelFormatType(pixelBuffer) == kCVPixelFormatType_OneComponent8; + glInfo.format = oneComponent8 ? PixelFormat::ALPHA_8 : PixelFormat::RGBA_8888; glInfo.target = CVOpenGLESTextureGetTarget(texture); glInfo.id = CVOpenGLESTextureGetName(texture); - glInfo.format = sizedFormat; - auto oneComponent8 = - CVPixelBufferGetPixelFormatType(pixelBuffer) == kCVPixelFormatType_OneComponent8; glTexture = Resource::Wrap(context, new EAGLHardwareTexture(pixelBuffer)); - glTexture->sampler.glInfo = glInfo; - glTexture->sampler.config = oneComponent8 ? PixelConfig::ALPHA_8 : PixelConfig::RGBA_8888; + glTexture->sampler = glInfo; glTexture->texture = texture; return glTexture; } diff --git a/tgfx/src/gpu/opengl/eagl/EAGLNV12Texture.mm b/tgfx/src/gpu/opengl/eagl/EAGLNV12Texture.mm index 2d3332ed4e..3c2ffd29e5 100644 --- a/tgfx/src/gpu/opengl/eagl/EAGLNV12Texture.mm +++ b/tgfx/src/gpu/opengl/eagl/EAGLNV12Texture.mm @@ -17,15 +17,16 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// #include "EAGLNV12Texture.h" +#include "gpu/opengl/GLContext.h" #include "gpu/opengl/eagl/EAGLDevice.h" namespace tgfx { -static GLTextureInfo ToGLTexture(CVOpenGLESTextureRef texture, unsigned format) { - GLTextureInfo glInfo = {}; - glInfo.target = CVOpenGLESTextureGetTarget(texture); - glInfo.id = CVOpenGLESTextureGetName(texture); - glInfo.format = format; - return glInfo; +static GLSampler ToGLSampler(CVOpenGLESTextureRef texture, PixelFormat format) { + GLSampler sampler = {}; + sampler.target = CVOpenGLESTextureGetTarget(texture); + sampler.id = CVOpenGLESTextureGetName(texture); + sampler.format = format; + return sampler; } std::shared_ptr EAGLNV12Texture::MakeFrom(Context* context, @@ -44,16 +45,16 @@ static GLTextureInfo ToGLTexture(CVOpenGLESTextureRef texture, unsigned format) auto height = static_cast(CVPixelBufferGetHeight(pixelBuffer)); CVOpenGLESTextureRef outputTextureLuma = nil; CVOpenGLESTextureRef outputTextureChroma = nil; - auto oneComponentConfig = PixelConfig::Gray_8; auto gl = GLContext::Unwrap(context); - const auto& oneComponentFormat = gl->caps->getTextureFormat(oneComponentConfig); + auto lumaComponentFormat = PixelFormat::GRAY_8; + const auto& oneComponentFormat = gl->caps->getTextureFormat(lumaComponentFormat); // 返回的 texture 对象是一个强引用计数为 1 的对象。 CVOpenGLESTextureCacheCreateTextureFromImage( kCFAllocatorDefault, textureCache, pixelBuffer, NULL, GL::TEXTURE_2D, oneComponentFormat.internalFormatTexImage, width, height, oneComponentFormat.externalFormat, GL::UNSIGNED_BYTE, 0, &outputTextureLuma); - auto twoComponentConfig = PixelConfig::RG_88; - const auto& twoComponentFormat = gl->caps->getTextureFormat(twoComponentConfig); + auto chromaComponentFormat = PixelFormat::RG_88; + const auto& twoComponentFormat = gl->caps->getTextureFormat(chromaComponentFormat); // 返回的 texture 对象是一个强引用计数为 1 的对象。 CVOpenGLESTextureCacheCreateTextureFromImage( kCFAllocatorDefault, textureCache, pixelBuffer, NULL, GL::TEXTURE_2D, @@ -64,11 +65,9 @@ static GLTextureInfo ToGLTexture(CVOpenGLESTextureRef texture, unsigned format) } auto texture = Resource::Wrap(context, new EAGLNV12Texture(pixelBuffer, colorSpace, colorRange)); texture->lumaTexture = outputTextureLuma; - texture->samplers.emplace_back(oneComponentConfig, - ToGLTexture(outputTextureLuma, oneComponentFormat.sizedFormat)); + texture->samplers.push_back(ToGLSampler(outputTextureLuma, lumaComponentFormat)); texture->chromaTexture = outputTextureChroma; - texture->samplers.emplace_back(twoComponentConfig, - ToGLTexture(outputTextureChroma, twoComponentFormat.sizedFormat)); + texture->samplers.push_back(ToGLSampler(outputTextureChroma, chromaComponentFormat)); return texture; } diff --git a/tgfx/src/gpu/opengl/eagl/EAGLWindow.mm b/tgfx/src/gpu/opengl/eagl/EAGLWindow.mm index 7e7cf64421..a6062812d1 100644 --- a/tgfx/src/gpu/opengl/eagl/EAGLWindow.mm +++ b/tgfx/src/gpu/opengl/eagl/EAGLWindow.mm @@ -137,11 +137,11 @@ LOGE("EAGLWindow::onCreateSurface() Framebuffer is not complete!"); return nullptr; } - GLFrameBufferInfo glInfo = {}; + GLFrameBuffer glInfo = {}; glInfo.id = frameBufferID; - glInfo.format = GL::RGBA8; - BackendRenderTarget renderTarget(glInfo, static_cast(width), static_cast(height)); - return Surface::MakeFrom(context, renderTarget, ImageOrigin::BottomLeft); + glInfo.format = PixelFormat::RGBA_8888; + auto renderTarget = GLRenderTarget::MakeFrom(context, glInfo, static_cast(width), static_cast(height), ImageOrigin::BottomLeft); + return Surface::MakeFrom(context, renderTarget); } void EAGLWindow::onPresent(Context* context, int64_t) { diff --git a/tgfx/src/gpu/opengl/egl/EGLHardwareTexture.cpp b/tgfx/src/gpu/opengl/egl/EGLHardwareTexture.cpp index 1fb5944266..c7ba74cf07 100644 --- a/tgfx/src/gpu/opengl/egl/EGLHardwareTexture.cpp +++ b/tgfx/src/gpu/opengl/egl/EGLHardwareTexture.cpp @@ -70,24 +70,25 @@ std::shared_ptr EGLHardwareTexture::MakeFrom(Context* contex if (eglImage == EGL_NO_IMAGE_KHR) { return nullptr; } - GLTextureInfo glInfo = {}; - glGenTextures(1, &glInfo.id); - if (glInfo.id == 0) { + GLSampler sampler = {}; + sampler.target = GL_TEXTURE_2D; + sampler.format = PixelFormat::RGBA_8888; + glGenTextures(1, &sampler.id); + if (sampler.id == 0) { eglext::eglDestroyImageKHR(display, eglImage); return nullptr; } - glBindTexture(GL_TEXTURE_2D, glInfo.id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - eglext::glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage); + glBindTexture(sampler.target, sampler.id); + glTexParameteri(sampler.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(sampler.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(sampler.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(sampler.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + eglext::glEGLImageTargetTexture2DOES(sampler.target, (GLeglImageOES)eglImage); AHardwareBuffer_Desc desc; HardwareBufferInterface::Describe(hardwareBuffer, &desc); glTexture = Resource::Wrap( context, new EGLHardwareTexture(hardwareBuffer, eglImage, desc.width, desc.height)); - glTexture->sampler.glInfo = glInfo; - glTexture->sampler.config = PixelConfig::RGBA_8888; + glTexture->sampler = sampler; return glTexture; } @@ -110,8 +111,7 @@ void EGLHardwareTexture::ComputeRecycleKey(BytesKey* recycleKey, void* hardwareB } void EGLHardwareTexture::onRelease(Context* context) { - auto gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &sampler.glInfo.id); + glDeleteTextures(1, &sampler.id); auto display = static_cast(context->device())->getDisplay(); eglext::eglDestroyImageKHR(display, eglImage); } diff --git a/tgfx/src/gpu/opengl/egl/EGLWindow.cpp b/tgfx/src/gpu/opengl/egl/EGLWindow.cpp index 24ef68cb9d..6727c36d94 100644 --- a/tgfx/src/gpu/opengl/egl/EGLWindow.cpp +++ b/tgfx/src/gpu/opengl/egl/EGLWindow.cpp @@ -19,6 +19,7 @@ #include "gpu/opengl/egl/EGLWindow.h" #include #include +#include "gpu/opengl/GLRenderTarget.h" namespace tgfx { std::shared_ptr EGLWindow::Current() { @@ -53,11 +54,12 @@ std::shared_ptr EGLWindow::onCreateSurface(Context* context) { if (width <= 0 || height <= 0) { return nullptr; } - GLFrameBufferInfo glInfo = {}; - glInfo.id = 0; - glInfo.format = GL_RGBA8; - BackendRenderTarget renderTarget(glInfo, width, height); - return Surface::MakeFrom(context, renderTarget, ImageOrigin::BottomLeft); + GLFrameBuffer frameBuffer = {}; + frameBuffer.id = 0; + frameBuffer.format = PixelFormat::RGBA_8888; + auto renderTarget = + GLRenderTarget::MakeFrom(context, frameBuffer, width, height, ImageOrigin::BottomLeft); + return Surface::MakeFrom(context, renderTarget); } void EGLWindow::onPresent(Context*, int64_t presentationTime) { diff --git a/tgfx/src/gpu/opengl/qt/QGLWindow.cpp b/tgfx/src/gpu/opengl/qt/QGLWindow.cpp index 1a671f061d..37eee40825 100644 --- a/tgfx/src/gpu/opengl/qt/QGLWindow.cpp +++ b/tgfx/src/gpu/opengl/qt/QGLWindow.cpp @@ -72,7 +72,7 @@ QSGTexture* QGLWindow::getTexture() { delete outTexture; outTexture = nullptr; } - auto textureID = frontTexture->getGLInfo().id; + auto textureID = frontTexture->glSampler().id; auto width = static_cast(ceil(quickItem->width())); auto height = static_cast(ceil(quickItem->height())); outTexture = nativeWindow->createTextureFromId(textureID, QSize(width, height), @@ -97,10 +97,11 @@ std::shared_ptr QGLWindow::onCreateSurface(Context* context) { if (width <= 0 || height <= 0) { return nullptr; } - frontTexture = GLTexture::MakeRGBA(context, width, height); - backTexture = GLTexture::MakeRGBA(context, width, height); - renderTarget = GLRenderTarget::MakeFrom(context, backTexture.get()); - return GLSurface::MakeFrom(context, renderTarget); + frontTexture = std::static_pointer_cast(Texture::MakeRGBA(context, width, height)); + backTexture = std::static_pointer_cast(Texture::MakeRGBA(context, width, height)); + auto surface = Surface::MakeFrom(context, backTexture); + renderTarget = std::static_pointer_cast(surface->getRenderTarget()); + return surface; } void QGLWindow::onPresent(Context* context, int64_t) { @@ -110,9 +111,9 @@ void QGLWindow::onPresent(Context* context, int64_t) { auto gl = GLContext::Unwrap(context); std::swap(frontTexture, backTexture); gl->flush(); - gl->bindFramebuffer(GL_FRAMEBUFFER, renderTarget->getGLInfo().id); + gl->bindFramebuffer(GL_FRAMEBUFFER, renderTarget->glFrameBuffer().id); gl->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - backTexture->getGLInfo().id, 0); + backTexture->glSampler().id, 0); gl->bindFramebuffer(GL_FRAMEBUFFER, 0); invalidateTexture(); }