GPU: add offscreen buffer drawing utility functions.
This commit is contained in:
@@ -652,7 +652,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
|||||||
sizey = (scene->r.size * scene->r.ysch) / 100;
|
sizey = (scene->r.size * scene->r.ysch) / 100;
|
||||||
|
|
||||||
/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
|
/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
|
||||||
ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, err_out);
|
ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, true, err_out);
|
||||||
|
|
||||||
if (!ofs) {
|
if (!ofs) {
|
||||||
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
|
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
|
|||||||
void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, unsigned int *r_rect)
|
void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, unsigned int *r_rect)
|
||||||
{
|
{
|
||||||
char err_out[256] = "unknown";
|
char err_out[256] = "unknown";
|
||||||
GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, false, err_out);
|
GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, true, false, err_out);
|
||||||
|
|
||||||
GPU_offscreen_bind(offscreen, true);
|
GPU_offscreen_bind(offscreen, true);
|
||||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
|
|||||||
@@ -1918,6 +1918,10 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
|
|||||||
view3d_draw_view(C, ar);
|
view3d_draw_view(C, ar);
|
||||||
GPU_viewport_unbind(rv3d->viewport);
|
GPU_viewport_unbind(rv3d->viewport);
|
||||||
|
|
||||||
|
rcti rect = ar->winrct;
|
||||||
|
BLI_rcti_translate(&rect, -ar->winrct.xmin, -ar->winrct.ymin);
|
||||||
|
GPU_viewport_draw_to_screen(rv3d->viewport, &rect);
|
||||||
|
|
||||||
v3d->flag |= V3D_INVALID_BACKBUF;
|
v3d->flag |= V3D_INVALID_BACKBUF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2130,7 +2134,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
|
|||||||
|
|
||||||
if (own_ofs) {
|
if (own_ofs) {
|
||||||
/* bind */
|
/* bind */
|
||||||
ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, false, err_out);
|
ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out);
|
||||||
if (ofs == NULL) {
|
if (ofs == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ static void backdrawview3d(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!rv3d->gpuoffscreen) {
|
if (!rv3d->gpuoffscreen) {
|
||||||
rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, false, error);
|
rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, true, false, error);
|
||||||
|
|
||||||
if (!rv3d->gpuoffscreen)
|
if (!rv3d->gpuoffscreen)
|
||||||
fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
|
fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
|
||||||
|
|||||||
@@ -83,14 +83,16 @@ void GPU_framebuffer_recursive_downsample(
|
|||||||
* - wrapper around framebuffer and texture for simple offscreen drawing
|
* - wrapper around framebuffer and texture for simple offscreen drawing
|
||||||
* - changes size if graphics card can't support it */
|
* - changes size if graphics card can't support it */
|
||||||
|
|
||||||
GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool high_bitdepth, char err_out[256]);
|
GPUOffScreen *GPU_offscreen_create(int width, int height, int samples,
|
||||||
|
bool depth, bool high_bitdepth, char err_out[256]);
|
||||||
void GPU_offscreen_free(GPUOffScreen *ofs);
|
void GPU_offscreen_free(GPUOffScreen *ofs);
|
||||||
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
|
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
|
||||||
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
|
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
|
||||||
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
|
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
|
||||||
|
void GPU_offscreen_blit(GPUOffScreen *ofs, int x, int y);
|
||||||
int GPU_offscreen_width(const GPUOffScreen *ofs);
|
int GPU_offscreen_width(const GPUOffScreen *ofs);
|
||||||
int GPU_offscreen_height(const GPUOffScreen *ofs);
|
int GPU_offscreen_height(const GPUOffScreen *ofs);
|
||||||
int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
|
struct GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs);
|
||||||
|
|
||||||
void GPU_offscreen_viewport_data_get(
|
void GPU_offscreen_viewport_data_get(
|
||||||
GPUOffScreen *ofs,
|
GPUOffScreen *ofs,
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ typedef struct ViewportEngineData_Info {
|
|||||||
GPUViewport *GPU_viewport_create(void);
|
GPUViewport *GPU_viewport_create(void);
|
||||||
void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
|
void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
|
||||||
void GPU_viewport_unbind(GPUViewport *viewport);
|
void GPU_viewport_unbind(GPUViewport *viewport);
|
||||||
|
void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect);
|
||||||
void GPU_viewport_free(GPUViewport *viewport);
|
void GPU_viewport_free(GPUViewport *viewport);
|
||||||
|
|
||||||
GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs);
|
GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs);
|
||||||
|
|||||||
@@ -641,7 +641,7 @@ struct GPUOffScreen {
|
|||||||
GPUTexture *depth;
|
GPUTexture *depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool high_bitdepth, char err_out[256])
|
GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256])
|
||||||
{
|
{
|
||||||
GPUOffScreen *ofs;
|
GPUOffScreen *ofs;
|
||||||
|
|
||||||
@@ -663,15 +663,17 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool high
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out);
|
if (depth) {
|
||||||
if (!ofs->depth) {
|
ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out);
|
||||||
GPU_offscreen_free(ofs);
|
if (!ofs->depth) {
|
||||||
return NULL;
|
GPU_offscreen_free(ofs);
|
||||||
}
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) {
|
if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) {
|
||||||
GPU_offscreen_free(ofs);
|
GPU_offscreen_free(ofs);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (high_bitdepth) {
|
if (high_bitdepth) {
|
||||||
@@ -731,6 +733,24 @@ void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
|
|||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU_offscreen_blit(GPUOffScreen *ofs, int x, int y)
|
||||||
|
{
|
||||||
|
const int w = GPU_texture_width(ofs->color);
|
||||||
|
const int h = GPU_texture_height(ofs->color);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object);
|
||||||
|
GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
|
||||||
|
|
||||||
|
if (status == GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gpu_print_framebuffer_error(status, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
|
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
|
||||||
{
|
{
|
||||||
const int w = GPU_texture_width(ofs->color);
|
const int w = GPU_texture_width(ofs->color);
|
||||||
@@ -818,9 +838,9 @@ int GPU_offscreen_height(const GPUOffScreen *ofs)
|
|||||||
return GPU_texture_height(ofs->color);
|
return GPU_texture_height(ofs->color);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
|
GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs)
|
||||||
{
|
{
|
||||||
return GPU_texture_opengl_bindcode(ofs->color);
|
return ofs->color;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only to be used by viewport code! */
|
/* only to be used by viewport code! */
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ cleanup:
|
|||||||
GPU_framebuffer_slots_bind(dfbl->default_fb, 0);
|
GPU_framebuffer_slots_bind(dfbl->default_fb, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_ofs_to_screen(GPUViewport *viewport)
|
static void draw_ofs_to_screen(GPUViewport *viewport, const rcti *rect)
|
||||||
{
|
{
|
||||||
DefaultTextureList *dtxl = viewport->txl;
|
DefaultTextureList *dtxl = viewport->txl;
|
||||||
|
|
||||||
@@ -483,6 +483,9 @@ static void draw_ofs_to_screen(GPUViewport *viewport)
|
|||||||
const float w = (float)GPU_texture_width(color);
|
const float w = (float)GPU_texture_width(color);
|
||||||
const float h = (float)GPU_texture_height(color);
|
const float h = (float)GPU_texture_height(color);
|
||||||
|
|
||||||
|
BLI_assert(w == BLI_rcti_size_x(rect) + 1);
|
||||||
|
BLI_assert(h == BLI_rcti_size_y(rect) + 1);
|
||||||
|
|
||||||
Gwn_VertFormat *format = immVertexFormat();
|
Gwn_VertFormat *format = immVertexFormat();
|
||||||
unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
|
unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
|
||||||
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
|
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
|
||||||
@@ -495,16 +498,16 @@ static void draw_ofs_to_screen(GPUViewport *viewport)
|
|||||||
immBegin(GWN_PRIM_TRI_STRIP, 4);
|
immBegin(GWN_PRIM_TRI_STRIP, 4);
|
||||||
|
|
||||||
immAttrib2f(texcoord, 0.0f, 0.0f);
|
immAttrib2f(texcoord, 0.0f, 0.0f);
|
||||||
immVertex2f(pos, 0.0f, 0.0f);
|
immVertex2f(pos, rect->xmin, rect->ymin);
|
||||||
|
|
||||||
immAttrib2f(texcoord, 1.0f, 0.0f);
|
immAttrib2f(texcoord, 1.0f, 0.0f);
|
||||||
immVertex2f(pos, w, 0.0f);
|
immVertex2f(pos, rect->xmin + w, rect->ymin);
|
||||||
|
|
||||||
immAttrib2f(texcoord, 0.0f, 1.0f);
|
immAttrib2f(texcoord, 0.0f, 1.0f);
|
||||||
immVertex2f(pos, 0.0f, h);
|
immVertex2f(pos, rect->xmin, rect->ymin + h);
|
||||||
|
|
||||||
immAttrib2f(texcoord, 1.0f, 1.0f);
|
immAttrib2f(texcoord, 1.0f, 1.0f);
|
||||||
immVertex2f(pos, w, h);
|
immVertex2f(pos, rect->xmin + w, rect->ymin + h);
|
||||||
|
|
||||||
immEnd();
|
immEnd();
|
||||||
|
|
||||||
@@ -523,9 +526,16 @@ void GPU_viewport_unbind(GPUViewport *viewport)
|
|||||||
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
|
||||||
|
{
|
||||||
|
DefaultFramebufferList *dfbl = viewport->fbl;
|
||||||
|
|
||||||
|
if (dfbl->default_fb) {
|
||||||
/* This might be bandwidth limiting */
|
/* This might be bandwidth limiting */
|
||||||
draw_ofs_to_screen(viewport);
|
draw_ofs_to_screen(viewport, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include "GPU_compositing.h"
|
#include "GPU_compositing.h"
|
||||||
#include "GPU_framebuffer.h"
|
#include "GPU_framebuffer.h"
|
||||||
|
#include "GPU_texture.h"
|
||||||
|
|
||||||
#include "../mathutils/mathutils.h"
|
#include "../mathutils/mathutils.h"
|
||||||
|
|
||||||
@@ -89,7 +90,8 @@ PyDoc_STRVAR(pygpu_offscreen_color_texture_doc, "Color texture.\n\n:type: int");
|
|||||||
static PyObject *pygpu_offscreen_color_texture_get(BPy_GPUOffScreen *self, void *UNUSED(type))
|
static PyObject *pygpu_offscreen_color_texture_get(BPy_GPUOffScreen *self, void *UNUSED(type))
|
||||||
{
|
{
|
||||||
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
|
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
|
||||||
return PyLong_FromLong(GPU_offscreen_color_texture(self->ofs));
|
GPUTexture *texture = GPU_offscreen_color_texture(self->ofs);
|
||||||
|
return PyLong_FromLong(GPU_texture_opengl_bindcode(texture));
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(pygpu_offscreen_bind_doc,
|
PyDoc_STRVAR(pygpu_offscreen_bind_doc,
|
||||||
@@ -354,7 +356,7 @@ static PyObject *pygpu_offscreen_new(PyObject *UNUSED(self), PyObject *args, PyO
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ofs = GPU_offscreen_create(width, height, samples, false, err_out);
|
ofs = GPU_offscreen_create(width, height, samples, true, false, err_out);
|
||||||
|
|
||||||
if (ofs == NULL) {
|
if (ofs == NULL) {
|
||||||
PyErr_Format(PyExc_RuntimeError,
|
PyErr_Format(PyExc_RuntimeError,
|
||||||
|
|||||||
Reference in New Issue
Block a user