2020-08-25 23:27:40 +02:00
|
|
|
/*
|
|
|
|
* 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
|
2020-08-29 01:13:54 +02:00
|
|
|
*
|
2021-02-05 21:32:31 +11:00
|
|
|
* Private frame buffer API.
|
2020-08-25 23:27:40 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2020-08-29 15:17:13 +02:00
|
|
|
#include "BLI_math_vector.h"
|
2020-08-29 01:13:54 +02:00
|
|
|
#include "BLI_span.hh"
|
|
|
|
|
2020-08-25 23:27:40 +02:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "GPU_framebuffer.h"
|
|
|
|
|
|
|
|
struct GPUTexture;
|
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
typedef enum GPUAttachmentType : int {
|
2020-08-25 23:27:40 +02:00
|
|
|
GPU_FB_DEPTH_ATTACHMENT = 0,
|
|
|
|
GPU_FB_DEPTH_STENCIL_ATTACHMENT,
|
|
|
|
GPU_FB_COLOR_ATTACHMENT0,
|
|
|
|
GPU_FB_COLOR_ATTACHMENT1,
|
|
|
|
GPU_FB_COLOR_ATTACHMENT2,
|
|
|
|
GPU_FB_COLOR_ATTACHMENT3,
|
|
|
|
GPU_FB_COLOR_ATTACHMENT4,
|
|
|
|
GPU_FB_COLOR_ATTACHMENT5,
|
|
|
|
/* Number of maximum output slots.
|
|
|
|
* We support 6 outputs for now (usually we wouldn't need more to preserve fill rate). */
|
|
|
|
/* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
|
|
|
|
* the maximum number of COLOR attachments specified by glDrawBuffers. */
|
2020-09-02 10:04:50 +10:00
|
|
|
GPU_FB_MAX_ATTACHMENT,
|
2020-08-29 01:13:54 +02:00
|
|
|
|
2020-08-25 23:27:40 +02:00
|
|
|
} GPUAttachmentType;
|
|
|
|
|
2020-10-02 11:39:27 +10:00
|
|
|
#define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHMENT - GPU_FB_COLOR_ATTACHMENT0)
|
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
inline constexpr GPUAttachmentType operator-(GPUAttachmentType a, int b)
|
|
|
|
{
|
|
|
|
return static_cast<GPUAttachmentType>(static_cast<int>(a) - b);
|
|
|
|
}
|
2020-08-25 23:27:40 +02:00
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
inline constexpr GPUAttachmentType operator+(GPUAttachmentType a, int b)
|
|
|
|
{
|
|
|
|
return static_cast<GPUAttachmentType>(static_cast<int>(a) + b);
|
|
|
|
}
|
2020-08-25 23:27:40 +02:00
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
inline GPUAttachmentType &operator++(GPUAttachmentType &a)
|
|
|
|
{
|
|
|
|
a = a + 1;
|
|
|
|
return a;
|
|
|
|
}
|
2020-08-25 23:27:40 +02:00
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
inline GPUAttachmentType &operator--(GPUAttachmentType &a)
|
|
|
|
{
|
|
|
|
a = a - 1;
|
|
|
|
return a;
|
|
|
|
}
|
2020-08-25 23:27:40 +02:00
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
namespace blender {
|
|
|
|
namespace gpu {
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
# define DEBUG_NAME_LEN 64
|
|
|
|
#else
|
|
|
|
# define DEBUG_NAME_LEN 16
|
|
|
|
#endif
|
2020-08-25 23:27:40 +02:00
|
|
|
|
|
|
|
class FrameBuffer {
|
2020-08-29 01:13:54 +02:00
|
|
|
protected:
|
2020-09-02 09:58:26 +10:00
|
|
|
/** Set of texture attachments to render to. DEPTH and DEPTH_STENCIL are mutually exclusive. */
|
2020-09-02 10:04:50 +10:00
|
|
|
GPUAttachment attachments_[GPU_FB_MAX_ATTACHMENT];
|
2020-08-29 01:13:54 +02:00
|
|
|
/** Is true if internal representation need to be updated. */
|
|
|
|
bool dirty_attachments_;
|
2020-09-02 09:58:26 +10:00
|
|
|
/** Size of attachment textures. */
|
2020-08-29 01:13:54 +02:00
|
|
|
int width_, height_;
|
|
|
|
/** Debug name. */
|
|
|
|
char name_[DEBUG_NAME_LEN];
|
2020-09-02 09:58:26 +10:00
|
|
|
/** Frame-buffer state. */
|
2020-11-05 17:59:07 +01:00
|
|
|
int viewport_[4] = {0};
|
|
|
|
int scissor_[4] = {0};
|
2020-08-29 15:17:13 +02:00
|
|
|
bool scissor_test_ = false;
|
2020-11-05 17:59:07 +01:00
|
|
|
bool dirty_state_ = true;
|
2020-08-25 23:27:40 +02:00
|
|
|
|
2021-04-30 11:20:39 -03:00
|
|
|
#ifndef GPU_NO_USE_PY_REFERENCES
|
2021-04-29 14:48:59 -03:00
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Reference of a pointer that needs to be cleaned when deallocating the frame-buffer.
|
|
|
|
* Points to #BPyGPUFrameBuffer.fb
|
|
|
|
*/
|
|
|
|
void **py_ref = nullptr;
|
|
|
|
#endif
|
|
|
|
|
2021-04-30 10:48:55 -03:00
|
|
|
public:
|
|
|
|
/* Reference of a pointer that needs to be cleaned when deallocating the frame-buffer.
|
|
|
|
* Points to BPyGPUFrameBuffer::fb */
|
|
|
|
void **ref = nullptr;
|
|
|
|
|
2020-08-25 23:27:40 +02:00
|
|
|
public:
|
2020-08-29 01:13:54 +02:00
|
|
|
FrameBuffer(const char *name);
|
|
|
|
virtual ~FrameBuffer();
|
|
|
|
|
|
|
|
virtual void bind(bool enabled_srgb) = 0;
|
|
|
|
virtual bool check(char err_out[256]) = 0;
|
|
|
|
virtual void clear(eGPUFrameBufferBits buffers,
|
|
|
|
const float clear_col[4],
|
|
|
|
float clear_depth,
|
|
|
|
uint clear_stencil) = 0;
|
|
|
|
virtual void clear_multi(const float (*clear_col)[4]) = 0;
|
2020-09-03 21:52:30 +02:00
|
|
|
virtual void clear_attachment(GPUAttachmentType type,
|
|
|
|
eGPUDataFormat data_format,
|
|
|
|
const void *clear_value) = 0;
|
2020-08-29 01:13:54 +02:00
|
|
|
|
|
|
|
virtual void read(eGPUFrameBufferBits planes,
|
|
|
|
eGPUDataFormat format,
|
|
|
|
const int area[4],
|
|
|
|
int channel_len,
|
|
|
|
int slot,
|
|
|
|
void *r_data) = 0;
|
|
|
|
|
|
|
|
virtual void blit_to(eGPUFrameBufferBits planes,
|
|
|
|
int src_slot,
|
|
|
|
FrameBuffer *dst,
|
|
|
|
int dst_slot,
|
|
|
|
int dst_offset_x,
|
|
|
|
int dst_offset_y) = 0;
|
|
|
|
|
|
|
|
void attachment_set(GPUAttachmentType type, const GPUAttachment &new_attachment);
|
2020-09-05 17:37:01 +02:00
|
|
|
void attachment_remove(GPUAttachmentType type);
|
2020-08-29 01:13:54 +02:00
|
|
|
|
|
|
|
void recursive_downsample(int max_lvl,
|
|
|
|
void (*callback)(void *userData, int level),
|
|
|
|
void *userData);
|
|
|
|
|
2020-08-29 14:03:15 +02:00
|
|
|
inline void size_set(int width, int height)
|
|
|
|
{
|
|
|
|
width_ = width;
|
|
|
|
height_ = height;
|
2020-08-29 15:17:13 +02:00
|
|
|
dirty_state_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void viewport_set(const int viewport[4])
|
|
|
|
{
|
|
|
|
if (!equals_v4v4_int(viewport_, viewport)) {
|
|
|
|
copy_v4_v4_int(viewport_, viewport);
|
|
|
|
dirty_state_ = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void scissor_set(const int scissor[4])
|
|
|
|
{
|
|
|
|
if (!equals_v4v4_int(scissor_, scissor)) {
|
|
|
|
copy_v4_v4_int(scissor_, scissor);
|
|
|
|
dirty_state_ = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void scissor_test_set(bool test)
|
|
|
|
{
|
|
|
|
scissor_test_ = test;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void viewport_get(int r_viewport[4]) const
|
|
|
|
{
|
|
|
|
copy_v4_v4_int(r_viewport, viewport_);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void scissor_get(int r_scissor[4]) const
|
|
|
|
{
|
|
|
|
copy_v4_v4_int(r_scissor, scissor_);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool scissor_test_get(void) const
|
|
|
|
{
|
|
|
|
return scissor_test_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void viewport_reset(void)
|
|
|
|
{
|
|
|
|
int viewport_rect[4] = {0, 0, width_, height_};
|
|
|
|
viewport_set(viewport_rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void scissor_reset(void)
|
|
|
|
{
|
|
|
|
int scissor_rect[4] = {0, 0, width_, height_};
|
|
|
|
scissor_set(scissor_rect);
|
2020-08-29 14:03:15 +02:00
|
|
|
}
|
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
inline GPUTexture *depth_tex(void) const
|
2020-08-25 23:27:40 +02:00
|
|
|
{
|
2020-08-29 01:13:54 +02:00
|
|
|
if (attachments_[GPU_FB_DEPTH_ATTACHMENT].tex) {
|
|
|
|
return attachments_[GPU_FB_DEPTH_ATTACHMENT].tex;
|
2020-08-25 23:27:40 +02:00
|
|
|
}
|
2020-08-29 01:13:54 +02:00
|
|
|
return attachments_[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;
|
2020-08-25 23:27:40 +02:00
|
|
|
};
|
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
inline GPUTexture *color_tex(int slot) const
|
2020-08-25 23:27:40 +02:00
|
|
|
{
|
2020-08-29 01:13:54 +02:00
|
|
|
return attachments_[GPU_FB_COLOR_ATTACHMENT0 + slot].tex;
|
2020-08-25 23:27:40 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* Syntactic sugar. */
|
2020-09-08 03:34:47 +02:00
|
|
|
static inline GPUFrameBuffer *wrap(FrameBuffer *vert)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<GPUFrameBuffer *>(vert);
|
|
|
|
}
|
|
|
|
static inline FrameBuffer *unwrap(GPUFrameBuffer *vert)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<FrameBuffer *>(vert);
|
|
|
|
}
|
|
|
|
static inline const FrameBuffer *unwrap(const GPUFrameBuffer *vert)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<const FrameBuffer *>(vert);
|
|
|
|
}
|
|
|
|
|
2020-08-29 01:13:54 +02:00
|
|
|
#undef DEBUG_NAME_LEN
|
|
|
|
|
2020-08-25 23:27:40 +02:00
|
|
|
} // namespace gpu
|
|
|
|
} // namespace blender
|