From 6e040b045ab1d94a877ab6f72f431c9b64e1121c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 13 Feb 2018 18:18:04 +0100 Subject: GPU: add offscreen buffer drawing utility functions. --- source/blender/editors/render/render_opengl.c | 2 +- source/blender/editors/screen/screen_draw.c | 2 +- source/blender/editors/space_view3d/view3d_draw.c | 6 +++- .../editors/space_view3d/view3d_draw_legacy.c | 2 +- source/blender/gpu/GPU_framebuffer.h | 6 ++-- source/blender/gpu/GPU_viewport.h | 1 + source/blender/gpu/intern/gpu_framebuffer.c | 42 ++++++++++++++++------ source/blender/gpu/intern/gpu_viewport.c | 22 ++++++++---- source/blender/python/intern/gpu_offscreen.c | 6 ++-- 9 files changed, 64 insertions(+), 25 deletions(-) (limited to 'source') diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 6e969067985..8eb9283790b 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -652,7 +652,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) sizey = (scene->r.size * scene->r.ysch) / 100; /* 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) { BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out); diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 2e4e9127ed6..6ea0a34c21d 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -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) { 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); glClearColor(0.0, 0.0, 0.0, 0.0); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index f96dead513c..c3a42cc0cad 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1918,6 +1918,10 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar) view3d_draw_view(C, ar); 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; } @@ -2130,7 +2134,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( if (own_ofs) { /* 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) { return NULL; } diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index aeb2cd11e39..1c6916d3820 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -286,7 +286,7 @@ static void backdrawview3d( } 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) fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index c58d98c201e..31f24aa7c2e 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -83,14 +83,16 @@ void GPU_framebuffer_recursive_downsample( * - wrapper around framebuffer and texture for simple offscreen drawing * - 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_bind(GPUOffScreen *ofs, bool save); void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore); 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_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( GPUOffScreen *ofs, diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index 580ff64befb..dff7e278ae1 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -98,6 +98,7 @@ typedef struct ViewportEngineData_Info { GPUViewport *GPU_viewport_create(void); void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect); void GPU_viewport_unbind(GPUViewport *viewport); +void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect); void GPU_viewport_free(GPUViewport *viewport); GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs); diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index 7b1f5c80246..2c38319906c 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -641,7 +641,7 @@ struct GPUOffScreen { 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; @@ -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 (!ofs->depth) { - GPU_offscreen_free(ofs); - return NULL; - } + if (depth) { + ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out); + if (!ofs->depth) { + GPU_offscreen_free(ofs); + return NULL; + } - if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) { - GPU_offscreen_free(ofs); - return NULL; + if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) { + GPU_offscreen_free(ofs); + return NULL; + } } if (high_bitdepth) { @@ -731,6 +733,24 @@ void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore) 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) { 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); } -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! */ diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 3ef53b3a6c3..fc045805874 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -474,7 +474,7 @@ cleanup: 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; @@ -483,6 +483,9 @@ static void draw_ofs_to_screen(GPUViewport *viewport) const float w = (float)GPU_texture_width(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(); 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); @@ -495,16 +498,16 @@ static void draw_ofs_to_screen(GPUViewport *viewport) immBegin(GWN_PRIM_TRI_STRIP, 4); immAttrib2f(texcoord, 0.0f, 0.0f); - immVertex2f(pos, 0.0f, 0.0f); + immVertex2f(pos, rect->xmin, rect->ymin); immAttrib2f(texcoord, 1.0f, 0.0f); - immVertex2f(pos, w, 0.0f); + immVertex2f(pos, rect->xmin + w, rect->ymin); immAttrib2f(texcoord, 0.0f, 1.0f); - immVertex2f(pos, 0.0f, h); + immVertex2f(pos, rect->xmin, rect->ymin + h); immAttrib2f(texcoord, 1.0f, 1.0f); - immVertex2f(pos, w, h); + immVertex2f(pos, rect->xmin + w, rect->ymin + h); immEnd(); @@ -523,9 +526,16 @@ void GPU_viewport_unbind(GPUViewport *viewport) glEnable(GL_SCISSOR_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 */ - draw_ofs_to_screen(viewport); + draw_ofs_to_screen(viewport, rect); } } diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c index 91d407d18a8..2da0227cdca 100644 --- a/source/blender/python/intern/gpu_offscreen.c +++ b/source/blender/python/intern/gpu_offscreen.c @@ -39,6 +39,7 @@ #include "GPU_compositing.h" #include "GPU_framebuffer.h" +#include "GPU_texture.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)) { 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, @@ -354,7 +356,7 @@ static PyObject *pygpu_offscreen_new(PyObject *UNUSED(self), PyObject *args, PyO 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) { PyErr_Format(PyExc_RuntimeError, -- cgit v1.2.3