| 
									
										
										
										
											2015-12-06 21:20:19 +01: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) 2005 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 11:23:17 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup gpu | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  | #include "BLI_math_base.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 19:57:58 +01:00
										 |  |  | #include "GPU_batch.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-07 19:35:56 +02:00
										 |  |  | #include "GPU_capabilities.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | #include "GPU_shader.h"
 | 
					
						
							|  |  |  | #include "GPU_texture.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | #include "gpu_backend.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-08 03:01:45 +02:00
										 |  |  | #include "gpu_context_private.hh"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "gpu_private.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | #include "gpu_texture_private.hh"
 | 
					
						
							| 
									
										
										
										
											2018-06-11 20:50:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | #include "gpu_framebuffer_private.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | namespace blender::gpu { | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Constructor / Destructor
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | FrameBuffer::FrameBuffer(const char *name) | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   if (name) { | 
					
						
							|  |  |  |     BLI_strncpy(name_, name, sizeof(name_)); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   else { | 
					
						
							|  |  |  |     name_[0] = '\0'; | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   /* Force config on first use. */ | 
					
						
							|  |  |  |   dirty_attachments_ = true; | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  |   dirty_state_ = true; | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |   for (GPUAttachment &attachment : attachments_) { | 
					
						
							|  |  |  |     attachment.tex = nullptr; | 
					
						
							|  |  |  |     attachment.mip = -1; | 
					
						
							|  |  |  |     attachment.layer = -1; | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | FrameBuffer::~FrameBuffer() | 
					
						
							| 
									
										
										
										
											2018-06-11 20:50:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |   for (GPUAttachment &attachment : attachments_) { | 
					
						
							|  |  |  |     if (attachment.tex != nullptr) { | 
					
						
							|  |  |  |       reinterpret_cast<Texture *>(attachment.tex)->detach_from(this); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-11 20:50:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /** \} */ | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /** \name Attachments Management
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void FrameBuffer::attachment_set(GPUAttachmentType type, const GPUAttachment &new_attachment) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   if (new_attachment.mip == -1) { | 
					
						
							|  |  |  |     return; /* GPU_ATTACHMENT_LEAVE */ | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |   if (type >= GPU_FB_MAX_ATTACHMENT) { | 
					
						
							| 
									
										
										
										
											2017-06-08 20:12:58 +02:00
										 |  |  |     fprintf(stderr, | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |             "GPUFramebuffer: Error: Trying to attach texture to type %d but maximum slot is %d.\n", | 
					
						
							|  |  |  |             type - GPU_FB_COLOR_ATTACHMENT0, | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |             GPU_FB_MAX_COLOR_ATTACHMENT); | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											2017-06-08 20:12:58 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   if (new_attachment.tex) { | 
					
						
							|  |  |  |     if (new_attachment.layer > 0) { | 
					
						
							| 
									
										
										
										
											2020-09-03 21:52:30 +02:00
										 |  |  |       BLI_assert(GPU_texture_cube(new_attachment.tex) || GPU_texture_array(new_attachment.tex)); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (GPU_texture_stencil(new_attachment.tex)) { | 
					
						
							|  |  |  |       BLI_assert(ELEM(type, GPU_FB_DEPTH_STENCIL_ATTACHMENT)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (GPU_texture_depth(new_attachment.tex)) { | 
					
						
							|  |  |  |       BLI_assert(ELEM(type, GPU_FB_DEPTH_ATTACHMENT)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GPUAttachment &attachment = attachments_[type]; | 
					
						
							| 
									
										
										
										
											2017-06-08 20:12:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   if (attachment.tex == new_attachment.tex && attachment.layer == new_attachment.layer && | 
					
						
							|  |  |  |       attachment.mip == new_attachment.mip) { | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |     return; /* Exact same texture already bound here. */ | 
					
						
							| 
									
										
										
										
											2017-06-16 13:25:22 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   /* Unbind previous and bind new. */ | 
					
						
							| 
									
										
										
										
											2020-09-19 14:32:41 +10:00
										 |  |  |   /* TODO(fclem): cleanup the casts. */ | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   if (attachment.tex) { | 
					
						
							| 
									
										
										
										
											2020-09-05 17:37:01 +02:00
										 |  |  |     reinterpret_cast<Texture *>(attachment.tex)->detach_from(this); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-06-08 20:12:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   attachment = new_attachment; | 
					
						
							| 
									
										
										
										
											2017-06-08 20:12:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   /* Might be null if this is for unbinding. */ | 
					
						
							|  |  |  |   if (attachment.tex) { | 
					
						
							| 
									
										
										
										
											2020-09-05 17:37:01 +02:00
										 |  |  |     reinterpret_cast<Texture *>(attachment.tex)->attach_to(this, type); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* GPU_ATTACHMENT_NONE */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-06-16 13:25:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   dirty_attachments_ = true; | 
					
						
							| 
									
										
										
										
											2017-06-16 13:25:22 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:37:01 +02:00
										 |  |  | void FrameBuffer::attachment_remove(GPUAttachmentType type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   attachments_[type] = GPU_ATTACHMENT_NONE; | 
					
						
							|  |  |  |   dirty_attachments_ = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void FrameBuffer::recursive_downsample(int max_lvl, | 
					
						
							|  |  |  |                                        void (*callback)(void *userData, int level), | 
					
						
							|  |  |  |                                        void *userData) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  |   /* Bind to make sure the frame-buffer is up to date. */ | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   this->bind(true); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:36:53 +02:00
										 |  |  |   /* FIXME(fclem): This assumes all mips are defined which may not be the case. */ | 
					
						
							|  |  |  |   max_lvl = min_ii(max_lvl, floor(log2(max_ii(width_, height_)))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int mip_lvl = 1; mip_lvl <= max_lvl; mip_lvl++) { | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  |     /* Replace attached mip-level for each attachment. */ | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |     for (GPUAttachment &attachment : attachments_) { | 
					
						
							|  |  |  |       Texture *tex = reinterpret_cast<Texture *>(attachment.tex); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |       if (tex != nullptr) { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |         /* Some Intel HDXXX have issue with rendering to a mipmap that is below
 | 
					
						
							|  |  |  |          * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case | 
					
						
							|  |  |  |          * we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */ | 
					
						
							| 
									
										
										
										
											2020-09-05 17:36:53 +02:00
										 |  |  |         int mip_max = (GPU_mip_render_workaround()) ? mip_lvl : (mip_lvl - 1); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |         /* Restrict fetches only to previous level. */ | 
					
						
							| 
									
										
										
										
											2020-09-05 17:36:53 +02:00
										 |  |  |         tex->mip_range_set(mip_lvl - 1, mip_max); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |         /* Bind next level. */ | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |         attachment.mip = mip_lvl; | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |     /* Update the internal attachments and viewport size. */ | 
					
						
							|  |  |  |     dirty_attachments_ = true; | 
					
						
							|  |  |  |     this->bind(true); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |     callback(userData, mip_lvl); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |   for (GPUAttachment &attachment : attachments_) { | 
					
						
							|  |  |  |     if (attachment.tex != nullptr) { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |       /* Reset mipmap level range. */ | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |       reinterpret_cast<Texture *>(attachment.tex)->mip_range_set(0, max_lvl); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |       /* Reset base level. NOTE: might not be the one bound at the start of this function. */ | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |       attachment.mip = 0; | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 17:46:24 +02:00
										 |  |  |   dirty_attachments_ = true; | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /** \} */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | }  // namespace blender::gpu
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name C-API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | using namespace blender; | 
					
						
							|  |  |  | using namespace blender::gpu; | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:28:26 +02:00
										 |  |  | GPUFrameBuffer *GPU_framebuffer_create(const char *name) | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   /* We generate the FB object later at first use in order to
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  |    * create the frame-buffer in the right opengl context. */ | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   return wrap(GPUBackend::get()->framebuffer_alloc(name)); | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void GPU_framebuffer_free(GPUFrameBuffer *gpu_fb) | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   delete unwrap(gpu_fb); | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /* ---------- Binding ----------- */ | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | void GPU_framebuffer_bind(GPUFrameBuffer *gpu_fb) | 
					
						
							| 
									
										
										
										
											2017-02-07 11:20:15 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   const bool enable_srgb = true; | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->bind(enable_srgb); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Workaround for binding a SRGB frame-buffer without doing the SRGB transform. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void GPU_framebuffer_bind_no_srgb(GPUFrameBuffer *gpu_fb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const bool enable_srgb = false; | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->bind(enable_srgb); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-07 11:20:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * For stereo rendering. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void GPU_backbuffer_bind(eGPUBackBuffer buffer) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context *ctx = Context::get(); | 
					
						
							| 
									
										
										
										
											2020-04-14 20:44:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   if (buffer == GPU_BACKBUFFER_LEFT) { | 
					
						
							|  |  |  |     ctx->back_left->bind(false); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:32:37 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   else { | 
					
						
							|  |  |  |     ctx->back_right->bind(false); | 
					
						
							| 
									
										
										
										
											2018-12-05 20:59:22 -02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-07 11:20:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void GPU_framebuffer_restore(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context::get()->back_left->bind(false); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-07 11:20:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | GPUFrameBuffer *GPU_framebuffer_active_get(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context *ctx = Context::get(); | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   return wrap(ctx ? ctx->active_fb : nullptr); | 
					
						
							| 
									
										
										
										
											2017-02-07 11:20:15 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /* Returns the default frame-buffer. Will always exists even if it's just a dummy. */ | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | GPUFrameBuffer *GPU_framebuffer_back_get(void) | 
					
						
							| 
									
										
										
										
											2020-08-18 14:43:18 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context *ctx = Context::get(); | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   return wrap(ctx ? ctx->back_left : nullptr); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | bool GPU_framebuffer_bound(GPUFrameBuffer *gpu_fb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (gpu_fb == GPU_framebuffer_active_get()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-08-18 14:43:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /* ---------- Attachment Management ----------- */ | 
					
						
							| 
									
										
										
										
											2020-08-18 14:43:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | bool GPU_framebuffer_check_valid(GPUFrameBuffer *gpu_fb, char err_out[256]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   return unwrap(gpu_fb)->check(err_out); | 
					
						
							| 
									
										
										
										
											2020-08-18 14:43:18 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  | void GPU_framebuffer_texture_attach_ex(GPUFrameBuffer *gpu_fb, GPUAttachment attachment, int slot) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-02 01:25:32 +02:00
										 |  |  |   Texture *tex = reinterpret_cast<Texture *>(attachment.tex); | 
					
						
							|  |  |  |   GPUAttachmentType type = tex->attachment_type(slot); | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->attachment_set(type, attachment); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 19:07:49 +02:00
										 |  |  | void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |   GPUAttachment attachment = GPU_ATTACHMENT_TEXTURE_MIP(tex, mip); | 
					
						
							|  |  |  |   GPU_framebuffer_texture_attach_ex(fb, attachment, slot); | 
					
						
							| 
									
										
										
										
											2020-08-30 19:07:49 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_framebuffer_texture_layer_attach( | 
					
						
							|  |  |  |     GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |   GPUAttachment attachment = GPU_ATTACHMENT_TEXTURE_LAYER_MIP(tex, layer, mip); | 
					
						
							|  |  |  |   GPU_framebuffer_texture_attach_ex(fb, attachment, slot); | 
					
						
							| 
									
										
										
										
											2020-08-30 19:07:49 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_framebuffer_texture_cubeface_attach( | 
					
						
							|  |  |  |     GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |   GPUAttachment attachment = GPU_ATTACHMENT_TEXTURE_CUBEFACE_MIP(tex, face, mip); | 
					
						
							|  |  |  |   GPU_framebuffer_texture_attach_ex(fb, attachment, slot); | 
					
						
							| 
									
										
										
										
											2020-08-30 19:07:49 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  | void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(tex)->detach_from(unwrap(fb)); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * First GPUAttachment in *config is always the depth/depth_stencil buffer. | 
					
						
							|  |  |  |  * Following GPUAttachments are color buffers. | 
					
						
							|  |  |  |  * Setting GPUAttachment.mip to -1 will leave the texture in this slot. | 
					
						
							|  |  |  |  * Setting GPUAttachment.tex to NULL will detach the texture in this slot. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void GPU_framebuffer_config_array(GPUFrameBuffer *gpu_fb, | 
					
						
							|  |  |  |                                   const GPUAttachment *config, | 
					
						
							|  |  |  |                                   int config_len) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   FrameBuffer *fb = unwrap(gpu_fb); | 
					
						
							| 
									
										
										
										
											2018-02-17 14:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |   const GPUAttachment &depth_attachment = config[0]; | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   Span<GPUAttachment> color_attachments(config + 1, config_len - 1); | 
					
						
							| 
									
										
										
										
											2016-08-19 00:52:52 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |   if (depth_attachment.mip == -1) { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |     /* GPU_ATTACHMENT_LEAVE */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |   else if (depth_attachment.tex == nullptr) { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |     /* GPU_ATTACHMENT_NONE: Need to clear both targets. */ | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |     fb->attachment_set(GPU_FB_DEPTH_STENCIL_ATTACHMENT, depth_attachment); | 
					
						
							|  |  |  |     fb->attachment_set(GPU_FB_DEPTH_ATTACHMENT, depth_attachment); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |     GPUAttachmentType type = GPU_texture_stencil(depth_attachment.tex) ? | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |                                  GPU_FB_DEPTH_STENCIL_ATTACHMENT : | 
					
						
							|  |  |  |                                  GPU_FB_DEPTH_ATTACHMENT; | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |     fb->attachment_set(type, depth_attachment); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-19 00:52:52 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   GPUAttachmentType type = GPU_FB_COLOR_ATTACHMENT0; | 
					
						
							| 
									
										
										
										
											2020-09-02 10:04:50 +10:00
										 |  |  |   for (const GPUAttachment &attachment : color_attachments) { | 
					
						
							|  |  |  |     fb->attachment_set(type, attachment); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |     ++type; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | /* ---------- Viewport & Scissor Region ----------- */ | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Viewport and scissor size is stored per frame-buffer. | 
					
						
							|  |  |  |  * It is only reset to its original dimensions explicitly OR when binding the frame-buffer after | 
					
						
							|  |  |  |  * modifying its attachments. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | void GPU_framebuffer_viewport_set(GPUFrameBuffer *gpu_fb, int x, int y, int width, int height) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int viewport_rect[4] = {x, y, width, height}; | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->viewport_set(viewport_rect); | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-25 14:18:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | void GPU_framebuffer_viewport_get(GPUFrameBuffer *gpu_fb, int r_viewport[4]) | 
					
						
							| 
									
										
										
										
											2018-03-25 14:18:39 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->viewport_get(r_viewport); | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-25 14:18:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Reset to its attachment(s) size. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | void GPU_framebuffer_viewport_reset(GPUFrameBuffer *gpu_fb) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->viewport_reset(); | 
					
						
							| 
									
										
										
										
											2018-03-25 14:18:39 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | /* ---------- Framebuffer Operations ----------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | void GPU_framebuffer_clear(GPUFrameBuffer *gpu_fb, | 
					
						
							| 
									
										
										
										
											2019-01-23 14:15:43 +11:00
										 |  |  |                            eGPUFrameBufferBits buffers, | 
					
						
							| 
									
										
										
										
											2018-09-12 12:18:35 +10:00
										 |  |  |                            const float clear_col[4], | 
					
						
							|  |  |  |                            float clear_depth, | 
					
						
							|  |  |  |                            uint clear_stencil) | 
					
						
							| 
									
										
										
										
											2018-03-25 14:18:39 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->clear(buffers, clear_col, clear_depth, clear_stencil); | 
					
						
							| 
									
										
										
										
											2018-03-25 14:18:39 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Clear all textures attached to this frame-buffer with a different color. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | void GPU_framebuffer_multi_clear(GPUFrameBuffer *gpu_fb, const float (*clear_cols)[4]) | 
					
						
							| 
									
										
										
										
											2020-03-09 16:27:24 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->clear_multi(clear_cols); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void GPU_clear_color(float red, float green, float blue, float alpha) | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   float clear_col[4] = {red, green, blue, alpha}; | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context::get()->active_fb->clear(GPU_COLOR_BIT, clear_col, 0.0f, 0x0); | 
					
						
							| 
									
										
										
										
											2020-07-16 02:50:55 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void GPU_clear_depth(float depth) | 
					
						
							| 
									
										
										
										
											2020-07-16 02:50:55 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   float clear_col[4] = {0}; | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context::get()->active_fb->clear(GPU_DEPTH_BIT, clear_col, depth, 0x0); | 
					
						
							| 
									
										
										
										
											2020-07-16 02:50:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 21:08:31 +02:00
										 |  |  | void GPU_framebuffer_read_depth( | 
					
						
							|  |  |  |     GPUFrameBuffer *gpu_fb, int x, int y, int w, int h, eGPUDataFormat format, void *data) | 
					
						
							| 
									
										
										
										
											2020-07-16 02:50:55 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   int rect[4] = {x, y, w, h}; | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->read(GPU_DEPTH_BIT, format, rect, 1, 1, data); | 
					
						
							| 
									
										
										
										
											2020-07-16 02:50:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | void GPU_framebuffer_read_color(GPUFrameBuffer *gpu_fb, | 
					
						
							| 
									
										
										
										
											2020-07-16 02:50:55 +02:00
										 |  |  |                                 int x, | 
					
						
							|  |  |  |                                 int y, | 
					
						
							|  |  |  |                                 int w, | 
					
						
							|  |  |  |                                 int h, | 
					
						
							|  |  |  |                                 int channels, | 
					
						
							|  |  |  |                                 int slot, | 
					
						
							|  |  |  |                                 eGPUDataFormat format, | 
					
						
							|  |  |  |                                 void *data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   int rect[4] = {x, y, w, h}; | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->read(GPU_COLOR_BIT, format, rect, channels, slot, data); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-19 14:32:41 +10:00
										 |  |  | /* TODO(fclem): rename to read_color. */ | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void GPU_frontbuffer_read_pixels( | 
					
						
							|  |  |  |     int x, int y, int w, int h, int channels, eGPUDataFormat format, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int rect[4] = {x, y, w, h}; | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context::get()->front_left->read(GPU_COLOR_BIT, format, rect, channels, 0, data); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* read_slot and write_slot are only used for color buffers. */ | 
					
						
							| 
									
										
										
										
											2020-09-19 14:32:41 +10:00
										 |  |  | /* TODO(fclem): port as texture operation. */ | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | void GPU_framebuffer_blit(GPUFrameBuffer *gpufb_read, | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |                           int read_slot, | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  |                           GPUFrameBuffer *gpufb_write, | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |                           int write_slot, | 
					
						
							| 
									
										
										
										
											2019-01-23 14:15:43 +11:00
										 |  |  |                           eGPUFrameBufferBits blit_buffers) | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   FrameBuffer *fb_read = unwrap(gpufb_read); | 
					
						
							|  |  |  |   FrameBuffer *fb_write = unwrap(gpufb_write); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   BLI_assert(blit_buffers != 0); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   FrameBuffer *prev_fb = Context::get()->active_fb; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |   GPUTexture *read_tex, *write_tex; | 
					
						
							|  |  |  |   if (blit_buffers & (GPU_DEPTH_BIT | GPU_STENCIL_BIT)) { | 
					
						
							|  |  |  |     read_tex = fb_read->depth_tex(); | 
					
						
							|  |  |  |     write_tex = fb_write->depth_tex(); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   else { | 
					
						
							|  |  |  |     read_tex = fb_read->color_tex(read_slot); | 
					
						
							|  |  |  |     write_tex = fb_write->color_tex(write_slot); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   if (blit_buffers & GPU_DEPTH_BIT) { | 
					
						
							| 
									
										
										
										
											2017-11-10 23:36:05 +01:00
										 |  |  |     BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex)); | 
					
						
							| 
									
										
										
										
											2017-11-14 20:49:13 +01:00
										 |  |  |     BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex)); | 
					
						
							| 
									
										
										
										
											2017-11-10 23:36:05 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   if (blit_buffers & GPU_STENCIL_BIT) { | 
					
						
							| 
									
										
										
										
											2017-11-10 23:36:05 +01:00
										 |  |  |     BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex)); | 
					
						
							| 
									
										
										
										
											2017-11-14 20:49:13 +01:00
										 |  |  |     BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex)); | 
					
						
							| 
									
										
										
										
											2017-11-10 23:36:05 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   fb_read->blit_to(blit_buffers, read_slot, fb_write, write_slot, 0, 0); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   /* FIXME(fclem) sRGB is not saved. */ | 
					
						
							|  |  |  |   prev_fb->bind(true); | 
					
						
							| 
									
										
										
										
											2017-02-15 15:15:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-22 02:01:58 +02:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  |  * Use this if you need to custom down-sample your texture and use the previous mip-level as | 
					
						
							| 
									
										
										
										
											2020-07-16 02:50:55 +02:00
										 |  |  |  * input. This function only takes care of the correct texture handling. It execute the callback | 
					
						
							|  |  |  |  * for each texture level. | 
					
						
							| 
									
										
										
										
											2019-03-19 15:17:46 +11:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-08-25 23:27:40 +02:00
										 |  |  | void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *gpu_fb, | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |                                           int max_lvl, | 
					
						
							|  |  |  |                                           void (*callback)(void *userData, int level), | 
					
						
							|  |  |  |                                           void *userData) | 
					
						
							| 
									
										
										
										
											2017-06-22 02:01:58 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_fb)->recursive_downsample(max_lvl, callback, userData); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /** \} */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							| 
									
										
										
										
											2021-01-10 21:05:17 -03:00
										 |  |  | /** \name GPUOffScreen
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-01-10 21:05:17 -03:00
										 |  |  |  * Container that holds a frame-buffer and its textures. | 
					
						
							|  |  |  |  * Might be bound to multiple contexts. | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | #define FRAMEBUFFER_STACK_DEPTH 16
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | static struct { | 
					
						
							|  |  |  |   GPUFrameBuffer *framebuffers[FRAMEBUFFER_STACK_DEPTH]; | 
					
						
							|  |  |  |   uint top; | 
					
						
							|  |  |  | } FrameBufferStack = {{nullptr}}; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-10 21:05:17 -03:00
										 |  |  | static void gpuPushFrameBuffer(GPUFrameBuffer *fb) | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   BLI_assert(FrameBufferStack.top < FRAMEBUFFER_STACK_DEPTH); | 
					
						
							|  |  |  |   FrameBufferStack.framebuffers[FrameBufferStack.top] = fb; | 
					
						
							|  |  |  |   FrameBufferStack.top++; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-10 21:05:17 -03:00
										 |  |  | static GPUFrameBuffer *gpuPopFrameBuffer() | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   BLI_assert(FrameBufferStack.top > 0); | 
					
						
							|  |  |  |   FrameBufferStack.top--; | 
					
						
							|  |  |  |   return FrameBufferStack.framebuffers[FrameBufferStack.top]; | 
					
						
							| 
									
										
										
										
											2017-06-22 02:01:58 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | #undef FRAMEBUFFER_STACK_DEPTH
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  | #define MAX_CTX_FB_LEN 3
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | struct GPUOffScreen { | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |   struct { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |     Context *ctx; | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |     GPUFrameBuffer *fb; | 
					
						
							|  |  |  |   } framebuffers[MAX_CTX_FB_LEN]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   GPUTexture *color; | 
					
						
							|  |  |  |   GPUTexture *depth; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Returns the correct frame-buffer for the current context. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  | static GPUFrameBuffer *gpu_offscreen_fb_get(GPUOffScreen *ofs) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context *ctx = Context::get(); | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |   BLI_assert(ctx); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |   for (auto &framebuffer : ofs->framebuffers) { | 
					
						
							|  |  |  |     if (framebuffer.fb == nullptr) { | 
					
						
							|  |  |  |       framebuffer.ctx = ctx; | 
					
						
							|  |  |  |       GPU_framebuffer_ensure_config(&framebuffer.fb, | 
					
						
							| 
									
										
										
										
											2020-07-25 18:40:19 +02:00
										 |  |  |                                     { | 
					
						
							|  |  |  |                                         GPU_ATTACHMENT_TEXTURE(ofs->depth), | 
					
						
							|  |  |  |                                         GPU_ATTACHMENT_TEXTURE(ofs->color), | 
					
						
							|  |  |  |                                     }); | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |     if (framebuffer.ctx == ctx) { | 
					
						
							|  |  |  |       return framebuffer.fb; | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* List is full, this should never happen or
 | 
					
						
							|  |  |  |    * it might just slow things down if it happens | 
					
						
							| 
									
										
										
										
											2019-07-07 15:38:41 +10:00
										 |  |  |    * regularly. In this case we just empty the list | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |    * and start over. This is most likely never going | 
					
						
							|  |  |  |    * to happen under normal usage. */ | 
					
						
							|  |  |  |   BLI_assert(0); | 
					
						
							|  |  |  |   printf( | 
					
						
							|  |  |  |       "Warning: GPUOffscreen used in more than 3 GPUContext. " | 
					
						
							|  |  |  |       "This may create performance drop.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |   for (auto &framebuffer : ofs->framebuffers) { | 
					
						
							|  |  |  |     GPU_framebuffer_free(framebuffer.fb); | 
					
						
							|  |  |  |     framebuffer.fb = nullptr; | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return gpu_offscreen_fb_get(ofs); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 18:18:04 +01:00
										 |  |  | GPUOffScreen *GPU_offscreen_create( | 
					
						
							| 
									
										
										
										
											2020-07-02 17:28:30 +02:00
										 |  |  |     int width, int height, bool depth, bool high_bitdepth, char err_out[256]) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-25 18:40:19 +02:00
										 |  |  |   GPUOffScreen *ofs = (GPUOffScreen *)MEM_callocN(sizeof(GPUOffScreen), __func__); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 16:30:17 +01:00
										 |  |  |   /* Sometimes areas can have 0 height or width and this will
 | 
					
						
							|  |  |  |    * create a 1D texture which we don't want. */ | 
					
						
							|  |  |  |   height = max_ii(1, height); | 
					
						
							|  |  |  |   width = max_ii(1, width); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-02 17:28:30 +02:00
										 |  |  |   ofs->color = GPU_texture_create_2d( | 
					
						
							| 
									
										
										
										
											2020-09-05 17:33:56 +02:00
										 |  |  |       "ofs_color", width, height, 1, (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, nullptr); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 18:18:04 +01:00
										 |  |  |   if (depth) { | 
					
						
							| 
									
										
										
										
											2020-09-05 17:33:56 +02:00
										 |  |  |     ofs->depth = GPU_texture_create_2d( | 
					
						
							|  |  |  |         "ofs_depth", width, height, 1, GPU_DEPTH24_STENCIL8, nullptr); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-20 20:51:54 +02:00
										 |  |  |   if ((depth && !ofs->depth) || !ofs->color) { | 
					
						
							| 
									
										
										
										
											2020-09-05 17:33:56 +02:00
										 |  |  |     BLI_snprintf(err_out, 256, "GPUTexture: Texture allocation failed."); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |     GPU_offscreen_free(ofs); | 
					
						
							|  |  |  |     return nullptr; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-20 20:51:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |   GPUFrameBuffer *fb = gpu_offscreen_fb_get(ofs); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   /* check validity at the very end! */ | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |   if (!GPU_framebuffer_check_valid(fb, err_out)) { | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |     GPU_offscreen_free(ofs); | 
					
						
							| 
									
										
										
										
											2018-06-04 09:09:12 +02:00
										 |  |  |     return nullptr; | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   } | 
					
						
							|  |  |  |   GPU_framebuffer_restore(); | 
					
						
							|  |  |  |   return ofs; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_offscreen_free(GPUOffScreen *ofs) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-07 12:21:11 +01:00
										 |  |  |   for (auto &framebuffer : ofs->framebuffers) { | 
					
						
							|  |  |  |     if (framebuffer.fb) { | 
					
						
							|  |  |  |       GPU_framebuffer_free(framebuffer.fb); | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-22 09:32:37 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ofs->color) { | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |     GPU_texture_free(ofs->color); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:32:37 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ofs->depth) { | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |     GPU_texture_free(ofs->depth); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:32:37 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-04 09:09:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   MEM_freeN(ofs); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPU_offscreen_bind(GPUOffScreen *ofs, bool save) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   if (save) { | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  |     GPUFrameBuffer *fb = GPU_framebuffer_active_get(); | 
					
						
							| 
									
										
										
										
											2021-01-10 21:05:17 -03:00
										 |  |  |     gpuPushFrameBuffer(fb); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   unwrap(gpu_offscreen_fb_get(ofs))->bind(false); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:04:08 +02:00
										 |  |  | void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  |   GPUFrameBuffer *fb = nullptr; | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   if (restore) { | 
					
						
							| 
									
										
										
										
											2021-01-10 21:05:17 -03:00
										 |  |  |     fb = gpuPopFrameBuffer(); | 
					
						
							| 
									
										
										
										
											2018-11-06 15:24:13 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fb) { | 
					
						
							|  |  |  |     GPU_framebuffer_bind(fb); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     GPU_framebuffer_restore(); | 
					
						
							| 
									
										
										
										
											2018-03-25 17:46:48 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-27 10:22:37 +02:00
										 |  |  | void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Context *ctx = Context::get(); | 
					
						
							| 
									
										
										
										
											2020-09-08 03:34:47 +02:00
										 |  |  |   FrameBuffer *ofs_fb = unwrap(gpu_offscreen_fb_get(ofs)); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   ofs_fb->blit_to(GPU_COLOR_BIT, 0, ctx->active_fb, 0, x, y); | 
					
						
							| 
									
										
										
										
											2018-04-27 10:22:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | void GPU_offscreen_read_pixels(GPUOffScreen *ofs, eGPUDataFormat format, void *pixels) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   BLI_assert(ELEM(format, GPU_DATA_UNSIGNED_BYTE, GPU_DATA_FLOAT)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  |   const int w = GPU_texture_width(ofs->color); | 
					
						
							|  |  |  |   const int h = GPU_texture_height(ofs->color); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |   GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs); | 
					
						
							|  |  |  |   GPU_framebuffer_read_color(ofs_fb, 0, 0, w, h, 4, 0, format, pixels); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int GPU_offscreen_width(const GPUOffScreen *ofs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return GPU_texture_width(ofs->color); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int GPU_offscreen_height(const GPUOffScreen *ofs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return GPU_texture_height(ofs->color); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 18:18:04 +01:00
										 |  |  | GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs) | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-13 18:18:04 +01:00
										 |  |  |   return ofs->color; | 
					
						
							| 
									
										
										
										
											2015-12-06 21:20:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * \note only to be used by viewport code! | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-05-03 02:50:29 +10:00
										 |  |  | void GPU_offscreen_viewport_data_get(GPUOffScreen *ofs, | 
					
						
							|  |  |  |                                      GPUFrameBuffer **r_fb, | 
					
						
							|  |  |  |                                      GPUTexture **r_color, | 
					
						
							|  |  |  |                                      GPUTexture **r_depth) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-13 21:31:46 +02:00
										 |  |  |   *r_fb = gpu_offscreen_fb_get(ofs); | 
					
						
							| 
									
										
										
										
											2017-05-03 02:50:29 +10:00
										 |  |  |   *r_color = ofs->color; | 
					
						
							|  |  |  |   *r_depth = ofs->depth; | 
					
						
							| 
									
										
										
										
											2017-05-09 15:09:39 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-26 15:17:31 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 09:58:26 +10:00
										 |  |  | /** \} */ |