From a92d77acf715f5a775e99b575cc8cc5238b11557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 2 Sep 2020 01:25:32 +0200 Subject: GPUTexture: Add skeleton of the new GLTexture class --- source/blender/gpu/CMakeLists.txt | 2 + source/blender/gpu/intern/gpu_backend.hh | 3 +- source/blender/gpu/intern/gpu_framebuffer.cc | 3 +- source/blender/gpu/intern/gpu_texture.cc | 44 +++++++++++ source/blender/gpu/intern/gpu_texture_private.hh | 83 +++++++++++++++++++- source/blender/gpu/opengl/gl_backend.hh | 6 ++ source/blender/gpu/opengl/gl_texture.cc | 98 ++++++++++++++++++++++++ source/blender/gpu/opengl/gl_texture.hh | 97 ++++++++++++++++++++++- 8 files changed, 328 insertions(+), 8 deletions(-) create mode 100644 source/blender/gpu/opengl/gl_texture.cc diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index cf0399b776d..5e126d097b4 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -96,6 +96,7 @@ set(SRC opengl/gl_shader.cc opengl/gl_shader_interface.cc opengl/gl_state.cc + opengl/gl_texture.cc opengl/gl_uniform_buffer.cc opengl/gl_vertex_array.cc @@ -143,6 +144,7 @@ set(SRC intern/gpu_shader_private.hh intern/gpu_shader_interface.hh intern/gpu_state_private.hh + intern/gpu_texture_private.hh intern/gpu_uniform_buffer_private.hh intern/gpu_vertex_format_private.h diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh index ec60e6b5704..06aff94dffe 100644 --- a/source/blender/gpu/intern/gpu_backend.hh +++ b/source/blender/gpu/intern/gpu_backend.hh @@ -34,6 +34,7 @@ class Batch; class DrawList; class FrameBuffer; class Shader; +class Texture; class UniformBuf; class GPUBackend { @@ -48,7 +49,7 @@ class GPUBackend { virtual DrawList *drawlist_alloc(int list_length) = 0; virtual FrameBuffer *framebuffer_alloc(const char *name) = 0; virtual Shader *shader_alloc(const char *name) = 0; - // virtual Texture *texture_alloc(void) = 0; + virtual Texture *texture_alloc(const char *name) = 0; virtual UniformBuf *uniformbuf_alloc(int size, const char *name) = 0; }; diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 6af34a60ffb..bb17ee8edf4 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -292,7 +292,8 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *gpu_fb, char err_out[256]) void GPU_framebuffer_texture_attach_ex(GPUFrameBuffer *gpu_fb, GPUAttachment attachment, int slot) { - GPUAttachmentType type = blender::gpu::Texture::attachment_type(attachment.tex, slot); + Texture *tex = reinterpret_cast(attachment.tex); + GPUAttachmentType type = tex->attachment_type(slot); reinterpret_cast(gpu_fb)->attachment_set(type, attachment); } diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index 0a22df96382..ced9ea5a498 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -46,6 +46,48 @@ #include "gpu_context_private.hh" #include "gpu_framebuffer_private.hh" +#include "gpu_texture_private.hh" + +namespace blender::gpu { + +/* -------------------------------------------------------------------- */ +/** \name Creation & Deletion + * \{ */ + +Texture::Texture(const char *name) +{ + if (name) { + BLI_strncpy(name_, name, sizeof(name_)); + } + else { + name_[0] = '\0'; + } +} + +Texture::~Texture() +{ +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operation + * \{ */ + +void Texture::attach_to(FrameBuffer *) +{ +} + +/** \} */ + +} // namespace blender::gpu + +/* -------------------------------------------------------------------- */ +/** \name C-API + * \{ */ + +using namespace blender::gpu; + static struct GPUTextureGlobal { /** Texture used in place of invalid textures (not loaded correctly, missing). */ GPUTexture *invalid_tex_1D; @@ -2238,6 +2280,8 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size) } } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name GPU Sampler Objects * diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index 6aa2a39046e..5eeb3d9e0f0 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -25,15 +25,88 @@ #include "BLI_assert.h" +#include "gpu_framebuffer_private.hh" + namespace blender { namespace gpu { +typedef enum eGPUTextureFlag { + GPU_TEXFORMAT_DEPTH = (1 << 0), + GPU_TEXFORMAT_STENCIL = (1 << 1), + GPU_TEXFORMAT_INTEGER = (1 << 2), + GPU_TEXFORMAT_FLOAT = (1 << 3), + + GPU_TEXTURE_1D = (1 << 10), + GPU_TEXTURE_2D = (1 << 11), + GPU_TEXTURE_3D = (1 << 12), + GPU_TEXTURE_CUBE = (1 << 13), + GPU_TEXTURE_ARRAY = (1 << 14), + GPU_TEXTURE_BUFFER = (1 << 15), + + GPU_TEXTURE_1D_ARRAY = (GPU_TEXTURE_1D | GPU_TEXTURE_ARRAY), + GPU_TEXTURE_2D_ARRAY = (GPU_TEXTURE_2D | GPU_TEXTURE_ARRAY), + GPU_TEXTURE_CUBE_ARRAY = (GPU_TEXTURE_CUBE | GPU_TEXTURE_ARRAY), + + GPU_TEXTURE_TARGET = (GPU_TEXTURE_1D | GPU_TEXTURE_2D | GPU_TEXTURE_3D | GPU_TEXTURE_CUBE | + GPU_TEXTURE_ARRAY), +} eGPUTextureFlag; + +ENUM_OPERATORS(eGPUTextureFlag) + +#ifdef DEBUG +# define DEBUG_NAME_LEN 64 +#else +# define DEBUG_NAME_LEN 8 +#endif + +/* Maximum number of FBOs a texture can be attached to. */ +#define GPU_TEX_MAX_FBO_ATTACHED 12 + class Texture { public: - /** TODO(fclem): make it a non-static function. */ - static GPUAttachmentType attachment_type(GPUTexture *tex, int slot) + /** Width & Height & Depth. */ + int w = 0, h = 0, d = 0; + /** Number of color/alpha channels. */ + int components = 0; + /** Internal data format and it's characteristics. */ + eGPUTextureFormat format; + eGPUTextureFlag flag; + /** Internal Sampler state. */ + eGPUSamplerState sampler_state; + /** Number of mipmaps this texture has. */ + int mipmaps = 0; + /** Reference counter. */ + int refcount = 0; + /** Width & Height (of source data), optional. */ + int src_w = 0, src_h = 0; + /** Framebuffer references to update on deletion. */ + GPUAttachmentType fb_attachment[GPU_TEX_MAX_FBO_ATTACHED]; + FrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED]; + + protected: + /** For debugging */ + char name_[DEBUG_NAME_LEN]; + + public: + Texture(const char *name); + virtual ~Texture(); + + virtual void bind(int slot) = 0; + virtual void update(void *data) = 0; + virtual void update_sub(void *data, int offset[3], int size[3]) = 0; + virtual void generate_mipmap(void) = 0; + virtual void copy_to(Texture *tex) = 0; + + virtual void swizzle_set(char swizzle_mask[4]) = 0; + + /* TODO(fclem) Legacy. Should be removed at some point. */ + virtual uint gl_bindcode_get(void) = 0; + + void attach_to(FrameBuffer *fb); + + GPUAttachmentType attachment_type(int slot) const { - switch (GPU_texture_format(tex)) { + switch (format) { case GPU_DEPTH_COMPONENT32F: case GPU_DEPTH_COMPONENT24: case GPU_DEPTH_COMPONENT16: @@ -44,10 +117,12 @@ class Texture { BLI_assert(slot == 0); return GPU_FB_DEPTH_STENCIL_ATTACHMENT; default: - return static_cast(GPU_FB_COLOR_ATTACHMENT0 + slot); + return GPU_FB_COLOR_ATTACHMENT0 + slot; } } }; +#undef DEBUG_NAME_LEN + } // namespace gpu } // namespace blender diff --git a/source/blender/gpu/opengl/gl_backend.hh b/source/blender/gpu/opengl/gl_backend.hh index 332350e47b5..6029ff9e309 100644 --- a/source/blender/gpu/opengl/gl_backend.hh +++ b/source/blender/gpu/opengl/gl_backend.hh @@ -32,6 +32,7 @@ #include "gl_drawlist.hh" #include "gl_framebuffer.hh" #include "gl_shader.hh" +#include "gl_texture.hh" #include "gl_uniform_buffer.hh" namespace blender { @@ -72,6 +73,11 @@ class GLBackend : public GPUBackend { return new GLShader(name); }; + Texture *texture_alloc(const char *name) + { + return new GLTexture(name); + }; + UniformBuf *uniformbuf_alloc(int size, const char *name) { return new GLUniformBuf(size, name); diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc new file mode 100644 index 00000000000..aaad281ed4e --- /dev/null +++ b/source/blender/gpu/opengl/gl_texture.cc @@ -0,0 +1,98 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + */ + +#include "BKE_global.h" + +#include "gl_backend.hh" + +#include "gl_texture.hh" + +namespace blender::gpu { + +/* -------------------------------------------------------------------- */ +/** \name Creation & Deletion + * \{ */ + +GLTexture::GLTexture(const char *name) : Texture(name) +{ + BLI_assert(GPU_context_active_get() != NULL); + + glGenTextures(1, &tex_id_); + +#ifndef __APPLE__ + if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) { + char sh_name[64]; + SNPRINTF(sh_name, "Texture-%s", name); + glObjectLabel(GL_TEXTURE, tex_id_, -1, sh_name); + } +#endif +} + +GLTexture::~GLTexture() +{ + GLBackend::get()->tex_free(tex_id_); +} + +void GLTexture::init(void) +{ +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operations + * \{ */ + +void GLTexture::bind(int /*slot*/) +{ +} + +void GLTexture::update(void * /*data*/) +{ +} + +void GLTexture::update_sub(void * /*data*/, int /*offset*/[3], int /*size*/[3]) +{ +} + +void GLTexture::generate_mipmap(void) +{ +} + +void GLTexture::copy_to(Texture * /*tex*/) +{ +} + +void GLTexture::swizzle_set(char /*swizzle_mask*/[4]) +{ +} + +/** \} */ + +/* TODO(fclem) Legacy. Should be removed at some point. */ +uint GLTexture::gl_bindcode_get(void) +{ + return tex_id_; +} + +} // namespace blender::gpu diff --git a/source/blender/gpu/opengl/gl_texture.hh b/source/blender/gpu/opengl/gl_texture.hh index c1194941038..513cef59e85 100644 --- a/source/blender/gpu/opengl/gl_texture.hh +++ b/source/blender/gpu/opengl/gl_texture.hh @@ -31,14 +31,107 @@ #pragma once +#include "MEM_guardedalloc.h" + #include "BLI_assert.h" +#include "gpu_texture_private.hh" + #include "glew-mx.h" namespace blender { namespace gpu { -static GLenum to_gl(eGPUDataFormat format) +#if 0 +class GLContext { + /** Currently bound textures. Updated before drawing. */ + GLuint bound_textures[64]; + GLuint bound_samplers[64]; + /** All sampler objects. Last one is for icon sampling. */ + GLuint samplers[GPU_SAMPLER_MAX + 1]; +}; +#endif + +class GLTexture : public Texture { + private: + /** Texture unit to which this texture is bound. */ + int slot = -1; + /** Target to bind the texture to (GL_TEXTURE_1D, GL_TEXTURE_2D, etc...)*/ + GLenum target_ = -1; + /** opengl identifier for texture. */ + GLuint tex_id_ = 0; + /** Legacy workaround for texture copy. */ + GLuint copy_fb = 0; + GPUContext *copy_fb_ctx = NULL; + + public: + GLTexture(const char *name); + ~GLTexture(); + + void bind(int slot) override; + void update(void *data) override; + void update_sub(void *data, int offset[3], int size[3]) override; + void generate_mipmap(void) override; + void copy_to(Texture *tex) override; + + void swizzle_set(char swizzle_mask[4]) override; + + /* TODO(fclem) Legacy. Should be removed at some point. */ + uint gl_bindcode_get(void) override; + + private: + void init(void); +}; + +static inline GLenum target_to_gl(eGPUTextureFlag target) +{ + switch (target & GPU_TEXTURE_TARGET) { + case GPU_TEXTURE_1D: + return GL_TEXTURE_1D; + case GPU_TEXTURE_1D | GPU_TEXTURE_ARRAY: + return GL_TEXTURE_1D_ARRAY; + case GPU_TEXTURE_2D: + return GL_TEXTURE_2D; + case GPU_TEXTURE_2D | GPU_TEXTURE_ARRAY: + return GL_TEXTURE_2D_ARRAY; + case GPU_TEXTURE_3D: + return GL_TEXTURE_3D; + case GPU_TEXTURE_CUBE: + return GL_TEXTURE_CUBE_MAP; + case GPU_TEXTURE_CUBE | GPU_TEXTURE_ARRAY: + return GL_TEXTURE_CUBE_MAP_ARRAY_ARB; + case GPU_TEXTURE_BUFFER: + return GL_TEXTURE_BUFFER; + default: + BLI_assert(0); + return GPU_TEXTURE_1D; + } +} + +static inline GLenum swizzle_to_gl(const char swizzle) +{ + switch (swizzle) { + default: + case 'x': + case 'r': + return GL_RED; + case 'y': + case 'g': + return GL_GREEN; + case 'z': + case 'b': + return GL_BLUE; + case 'w': + case 'a': + return GL_ALPHA; + case '0': + return GL_ZERO; + case '1': + return GL_ONE; + } +} + +static inline GLenum to_gl(eGPUDataFormat format) { switch (format) { case GPU_DATA_FLOAT: @@ -60,7 +153,7 @@ static GLenum to_gl(eGPUDataFormat format) } /* Assume Unorm / Float target. Used with glReadPixels. */ -static GLenum channel_len_to_gl(int channel_len) +static inline GLenum channel_len_to_gl(int channel_len) { switch (channel_len) { case 1: -- cgit v1.2.3