1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2005 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup gpu
22  */
23 
24 #include "BLI_string.h"
25 
26 #include "GPU_framebuffer.h"
27 #include "GPU_texture.h"
28 
29 #include "gpu_backend.hh"
30 #include "gpu_context_private.hh"
31 #include "gpu_framebuffer_private.hh"
32 #include "gpu_vertex_buffer_private.hh"
33 
34 #include "gpu_texture_private.hh"
35 
36 namespace blender::gpu {
37 
38 /* -------------------------------------------------------------------- */
39 /** \name Creation & Deletion
40  * \{ */
41 
Texture(const char * name)42 Texture::Texture(const char *name)
43 {
44   if (name) {
45     BLI_strncpy(name_, name, sizeof(name_));
46   }
47   else {
48     name_[0] = '\0';
49   }
50 
51   for (int i = 0; i < ARRAY_SIZE(fb_); i++) {
52     fb_[i] = NULL;
53   }
54 }
55 
~Texture()56 Texture::~Texture()
57 {
58   for (int i = 0; i < ARRAY_SIZE(fb_); i++) {
59     if (fb_[i] != NULL) {
60       fb_[i]->attachment_remove(fb_attachment_[i]);
61     }
62   }
63 }
64 
init_1D(int w,int layers,eGPUTextureFormat format)65 bool Texture::init_1D(int w, int layers, eGPUTextureFormat format)
66 {
67   w_ = w;
68   h_ = layers;
69   d_ = 0;
70   format_ = format;
71   format_flag_ = to_format_flag(format);
72   type_ = (layers > 0) ? GPU_TEXTURE_1D_ARRAY : GPU_TEXTURE_1D;
73   if ((format_flag_ & (GPU_FORMAT_DEPTH_STENCIL | GPU_FORMAT_INTEGER)) == 0) {
74     sampler_state = GPU_SAMPLER_FILTER;
75   }
76   return this->init_internal();
77 }
78 
init_2D(int w,int h,int layers,eGPUTextureFormat format)79 bool Texture::init_2D(int w, int h, int layers, eGPUTextureFormat format)
80 {
81   w_ = w;
82   h_ = h;
83   d_ = layers;
84   format_ = format;
85   format_flag_ = to_format_flag(format);
86   type_ = (layers > 0) ? GPU_TEXTURE_2D_ARRAY : GPU_TEXTURE_2D;
87   if ((format_flag_ & (GPU_FORMAT_DEPTH_STENCIL | GPU_FORMAT_INTEGER)) == 0) {
88     sampler_state = GPU_SAMPLER_FILTER;
89   }
90   return this->init_internal();
91 }
92 
init_3D(int w,int h,int d,eGPUTextureFormat format)93 bool Texture::init_3D(int w, int h, int d, eGPUTextureFormat format)
94 {
95   w_ = w;
96   h_ = h;
97   d_ = d;
98   format_ = format;
99   format_flag_ = to_format_flag(format);
100   type_ = GPU_TEXTURE_3D;
101   if ((format_flag_ & (GPU_FORMAT_DEPTH_STENCIL | GPU_FORMAT_INTEGER)) == 0) {
102     sampler_state = GPU_SAMPLER_FILTER;
103   }
104   return this->init_internal();
105 }
106 
init_cubemap(int w,int layers,eGPUTextureFormat format)107 bool Texture::init_cubemap(int w, int layers, eGPUTextureFormat format)
108 {
109   w_ = w;
110   h_ = w;
111   d_ = max_ii(1, layers) * 6;
112   format_ = format;
113   format_flag_ = to_format_flag(format);
114   type_ = (layers > 0) ? GPU_TEXTURE_CUBE_ARRAY : GPU_TEXTURE_CUBE;
115   if ((format_flag_ & (GPU_FORMAT_DEPTH_STENCIL | GPU_FORMAT_INTEGER)) == 0) {
116     sampler_state = GPU_SAMPLER_FILTER;
117   }
118   return this->init_internal();
119 }
120 
init_buffer(GPUVertBuf * vbo,eGPUTextureFormat format)121 bool Texture::init_buffer(GPUVertBuf *vbo, eGPUTextureFormat format)
122 {
123   /* See to_texture_format(). */
124   if (format == GPU_DEPTH_COMPONENT24) {
125     return false;
126   }
127   w_ = GPU_vertbuf_get_vertex_len(vbo);
128   h_ = 0;
129   d_ = 0;
130   format_ = format;
131   format_flag_ = to_format_flag(format);
132   type_ = GPU_TEXTURE_BUFFER;
133   return this->init_internal(vbo);
134 }
135 
136 /** \} */
137 
138 /* -------------------------------------------------------------------- */
139 /** \name Operation
140  * \{ */
141 
attach_to(FrameBuffer * fb,GPUAttachmentType type)142 void Texture::attach_to(FrameBuffer *fb, GPUAttachmentType type)
143 {
144   for (int i = 0; i < ARRAY_SIZE(fb_); i++) {
145     if (fb_[i] == NULL) {
146       fb_attachment_[i] = type;
147       fb_[i] = fb;
148       return;
149     }
150   }
151   BLI_assert(!"GPU: Error: Texture: Not enough attachment");
152 }
153 
detach_from(FrameBuffer * fb)154 void Texture::detach_from(FrameBuffer *fb)
155 {
156   for (int i = 0; i < ARRAY_SIZE(fb_); i++) {
157     if (fb_[i] == fb) {
158       fb_[i]->attachment_remove(fb_attachment_[i]);
159       fb_[i] = NULL;
160       return;
161     }
162   }
163   BLI_assert(!"GPU: Error: Texture: Framebuffer is not attached");
164 }
165 
update(eGPUDataFormat format,const void * data)166 void Texture::update(eGPUDataFormat format, const void *data)
167 {
168   int mip = 0;
169   int extent[3], offset[3] = {0, 0, 0};
170   this->mip_size_get(mip, extent);
171   this->update_sub(mip, offset, extent, format, data);
172 }
173 
174 /** \} */
175 
176 }  // namespace blender::gpu
177 
178 /* -------------------------------------------------------------------- */
179 /** \name C-API
180  * \{ */
181 
182 using namespace blender;
183 using namespace blender::gpu;
184 
185 /* ------ Memory Management ------ */
186 
GPU_texture_memory_usage_get(void)187 uint GPU_texture_memory_usage_get(void)
188 {
189   /* TODO(fclem): Do that inside the new Texture class. */
190   return 0;
191 }
192 
193 /* ------ Creation ------ */
194 
gpu_texture_create(const char * name,const int w,const int h,const int d,const eGPUTextureType type,int UNUSED (mips),eGPUTextureFormat tex_format,eGPUDataFormat data_format,const void * pixels)195 static inline GPUTexture *gpu_texture_create(const char *name,
196                                              const int w,
197                                              const int h,
198                                              const int d,
199                                              const eGPUTextureType type,
200                                              int UNUSED(mips),
201                                              eGPUTextureFormat tex_format,
202                                              eGPUDataFormat data_format,
203                                              const void *pixels)
204 {
205   Texture *tex = GPUBackend::get()->texture_alloc(name);
206   bool success = false;
207   switch (type) {
208     case GPU_TEXTURE_1D:
209     case GPU_TEXTURE_1D_ARRAY:
210       success = tex->init_1D(w, h, tex_format);
211       break;
212     case GPU_TEXTURE_2D:
213     case GPU_TEXTURE_2D_ARRAY:
214       success = tex->init_2D(w, h, d, tex_format);
215       break;
216     case GPU_TEXTURE_3D:
217       success = tex->init_3D(w, h, d, tex_format);
218       break;
219     case GPU_TEXTURE_CUBE:
220     case GPU_TEXTURE_CUBE_ARRAY:
221       success = tex->init_cubemap(w, d, tex_format);
222       break;
223     default:
224       break;
225   }
226 
227   if (!success) {
228     delete tex;
229     return NULL;
230   }
231   if (pixels) {
232     tex->update(data_format, pixels);
233   }
234   return reinterpret_cast<GPUTexture *>(tex);
235 }
236 
GPU_texture_create_1d(const char * name,int w,int mips,eGPUTextureFormat format,const float * data)237 GPUTexture *GPU_texture_create_1d(
238     const char *name, int w, int mips, eGPUTextureFormat format, const float *data)
239 {
240   return gpu_texture_create(name, w, 0, 0, GPU_TEXTURE_1D, mips, format, GPU_DATA_FLOAT, data);
241 }
242 
GPU_texture_create_1d_array(const char * name,int w,int h,int mips,eGPUTextureFormat format,const float * data)243 GPUTexture *GPU_texture_create_1d_array(
244     const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data)
245 {
246   return gpu_texture_create(
247       name, w, h, 0, GPU_TEXTURE_1D_ARRAY, mips, format, GPU_DATA_FLOAT, data);
248 }
249 
GPU_texture_create_2d(const char * name,int w,int h,int mips,eGPUTextureFormat format,const float * data)250 GPUTexture *GPU_texture_create_2d(
251     const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data)
252 {
253   return gpu_texture_create(name, w, h, 0, GPU_TEXTURE_2D, mips, format, GPU_DATA_FLOAT, data);
254 }
255 
GPU_texture_create_2d_array(const char * name,int w,int h,int d,int mips,eGPUTextureFormat format,const float * data)256 GPUTexture *GPU_texture_create_2d_array(
257     const char *name, int w, int h, int d, int mips, eGPUTextureFormat format, const float *data)
258 {
259   return gpu_texture_create(
260       name, w, h, d, GPU_TEXTURE_2D_ARRAY, mips, format, GPU_DATA_FLOAT, data);
261 }
262 
GPU_texture_create_3d(const char * name,int w,int h,int d,int mips,eGPUTextureFormat texture_format,eGPUDataFormat data_format,const void * data)263 GPUTexture *GPU_texture_create_3d(const char *name,
264                                   int w,
265                                   int h,
266                                   int d,
267                                   int mips,
268                                   eGPUTextureFormat texture_format,
269                                   eGPUDataFormat data_format,
270                                   const void *data)
271 {
272   return gpu_texture_create(
273       name, w, h, d, GPU_TEXTURE_3D, mips, texture_format, data_format, data);
274 }
275 
GPU_texture_create_cube(const char * name,int w,int mips,eGPUTextureFormat format,const float * data)276 GPUTexture *GPU_texture_create_cube(
277     const char *name, int w, int mips, eGPUTextureFormat format, const float *data)
278 {
279   return gpu_texture_create(name, w, w, 0, GPU_TEXTURE_CUBE, mips, format, GPU_DATA_FLOAT, data);
280 }
281 
GPU_texture_create_cube_array(const char * name,int w,int d,int mips,eGPUTextureFormat format,const float * data)282 GPUTexture *GPU_texture_create_cube_array(
283     const char *name, int w, int d, int mips, eGPUTextureFormat format, const float *data)
284 {
285   return gpu_texture_create(
286       name, w, w, d, GPU_TEXTURE_CUBE_ARRAY, mips, format, GPU_DATA_FLOAT, data);
287 }
288 
289 /* DDS texture loading. Return NULL if support is not available. */
GPU_texture_create_compressed_2d(const char * name,int w,int h,int miplen,eGPUTextureFormat tex_format,const void * data)290 GPUTexture *GPU_texture_create_compressed_2d(
291     const char *name, int w, int h, int miplen, eGPUTextureFormat tex_format, const void *data)
292 {
293   Texture *tex = GPUBackend::get()->texture_alloc(name);
294   bool success = tex->init_2D(w, h, 0, tex_format);
295 
296   if (!success) {
297     delete tex;
298     return NULL;
299   }
300   if (data) {
301     size_t ofs = 0;
302     for (int mip = 0; mip < miplen; mip++) {
303       int extent[3], offset[3] = {0, 0, 0};
304       tex->mip_size_get(mip, extent);
305 
306       size_t size = ((extent[0] + 3) / 4) * ((extent[1] + 3) / 4) * to_block_size(tex_format);
307       tex->update_sub(mip, offset, extent, to_data_format(tex_format), (uchar *)data + ofs);
308 
309       ofs += size;
310     }
311   }
312   return reinterpret_cast<GPUTexture *>(tex);
313 }
314 
GPU_texture_create_from_vertbuf(const char * name,GPUVertBuf * vert)315 GPUTexture *GPU_texture_create_from_vertbuf(const char *name, GPUVertBuf *vert)
316 {
317   eGPUTextureFormat tex_format = to_texture_format(GPU_vertbuf_get_format(vert));
318   Texture *tex = GPUBackend::get()->texture_alloc(name);
319 
320   bool success = tex->init_buffer(vert, tex_format);
321   if (!success) {
322     delete tex;
323     return NULL;
324   }
325   return reinterpret_cast<GPUTexture *>(tex);
326 }
327 
328 /* Create an error texture that will bind an invalid texture (pink) at draw time. */
GPU_texture_create_error(int dimension,bool is_array)329 GPUTexture *GPU_texture_create_error(int dimension, bool is_array)
330 {
331   float pixel[4] = {1.0f, 0.0f, 1.0f, 1.0f};
332   int w = 1;
333   int h = (dimension < 2 && !is_array) ? 0 : 1;
334   int d = (dimension < 3 && !is_array) ? 0 : 1;
335 
336   eGPUTextureType type = GPU_TEXTURE_3D;
337   type = (dimension == 2) ? (is_array ? GPU_TEXTURE_2D_ARRAY : GPU_TEXTURE_2D) : type;
338   type = (dimension == 1) ? (is_array ? GPU_TEXTURE_1D_ARRAY : GPU_TEXTURE_1D) : type;
339 
340   return gpu_texture_create("invalid_tex", w, h, d, type, 1, GPU_RGBA8, GPU_DATA_FLOAT, pixel);
341 }
342 
343 /* ------ Update ------ */
344 
GPU_texture_update_mipmap(GPUTexture * tex_,int miplvl,eGPUDataFormat data_format,const void * pixels)345 void GPU_texture_update_mipmap(GPUTexture *tex_,
346                                int miplvl,
347                                eGPUDataFormat data_format,
348                                const void *pixels)
349 {
350   Texture *tex = reinterpret_cast<Texture *>(tex_);
351   int extent[3] = {1, 1, 1}, offset[3] = {0, 0, 0};
352   tex->mip_size_get(miplvl, extent);
353   reinterpret_cast<Texture *>(tex)->update_sub(miplvl, offset, extent, data_format, pixels);
354 }
355 
GPU_texture_update_sub(GPUTexture * tex,eGPUDataFormat data_format,const void * pixels,int offset_x,int offset_y,int offset_z,int width,int height,int depth)356 void GPU_texture_update_sub(GPUTexture *tex,
357                             eGPUDataFormat data_format,
358                             const void *pixels,
359                             int offset_x,
360                             int offset_y,
361                             int offset_z,
362                             int width,
363                             int height,
364                             int depth)
365 {
366   int offset[3] = {offset_x, offset_y, offset_z};
367   int extent[3] = {width, height, depth};
368   reinterpret_cast<Texture *>(tex)->update_sub(0, offset, extent, data_format, pixels);
369 }
370 
GPU_texture_read(GPUTexture * tex_,eGPUDataFormat data_format,int miplvl)371 void *GPU_texture_read(GPUTexture *tex_, eGPUDataFormat data_format, int miplvl)
372 {
373   Texture *tex = reinterpret_cast<Texture *>(tex_);
374   return tex->read(miplvl, data_format);
375 }
376 
377 /**
378  * Fills the whole texture with the same data for all pixels.
379  * \warning Only work for 2D texture for now.
380  * \warning Only clears the mip 0 of the texture.
381  * \param data_format: data format of the pixel data.
382  * \param data: 1 pixel worth of data to fill the texture with.
383  */
GPU_texture_clear(GPUTexture * tex,eGPUDataFormat data_format,const void * data)384 void GPU_texture_clear(GPUTexture *tex, eGPUDataFormat data_format, const void *data)
385 {
386   BLI_assert(data != NULL); /* Do not accept NULL as parameter. */
387   reinterpret_cast<Texture *>(tex)->clear(data_format, data);
388 }
389 
390 /* NOTE: Updates only mip 0. */
GPU_texture_update(GPUTexture * tex,eGPUDataFormat data_format,const void * data)391 void GPU_texture_update(GPUTexture *tex, eGPUDataFormat data_format, const void *data)
392 {
393   reinterpret_cast<Texture *>(tex)->update(data_format, data);
394 }
395 
396 /* Makes data interpretation aware of the source layout.
397  * Skipping pixels correctly when changing rows when doing partial update.*/
GPU_unpack_row_length_set(uint len)398 void GPU_unpack_row_length_set(uint len)
399 {
400   Context::get()->state_manager->texture_unpack_row_length_set(len);
401 }
402 
403 /* ------ Binding ------ */
404 
GPU_texture_bind_ex(GPUTexture * tex_,eGPUSamplerState state,int unit,const bool UNUSED (set_number))405 void GPU_texture_bind_ex(GPUTexture *tex_,
406                          eGPUSamplerState state,
407                          int unit,
408                          const bool UNUSED(set_number))
409 {
410   Texture *tex = reinterpret_cast<Texture *>(tex_);
411   state = (state >= GPU_SAMPLER_MAX) ? tex->sampler_state : state;
412   Context::get()->state_manager->texture_bind(tex, state, unit);
413 }
414 
GPU_texture_bind(GPUTexture * tex_,int unit)415 void GPU_texture_bind(GPUTexture *tex_, int unit)
416 {
417   Texture *tex = reinterpret_cast<Texture *>(tex_);
418   Context::get()->state_manager->texture_bind(tex, tex->sampler_state, unit);
419 }
420 
GPU_texture_unbind(GPUTexture * tex_)421 void GPU_texture_unbind(GPUTexture *tex_)
422 {
423   Texture *tex = reinterpret_cast<Texture *>(tex_);
424   Context::get()->state_manager->texture_unbind(tex);
425 }
426 
GPU_texture_unbind_all(void)427 void GPU_texture_unbind_all(void)
428 {
429   Context::get()->state_manager->texture_unbind_all();
430 }
431 
GPU_texture_image_bind(GPUTexture * tex,int unit)432 void GPU_texture_image_bind(GPUTexture *tex, int unit)
433 {
434   Context::get()->state_manager->image_bind(unwrap(tex), unit);
435 }
436 
GPU_texture_image_unbind(GPUTexture * tex)437 void GPU_texture_image_unbind(GPUTexture *tex)
438 {
439   Context::get()->state_manager->image_unbind(unwrap(tex));
440 }
441 
GPU_texture_image_unbind_all(void)442 void GPU_texture_image_unbind_all(void)
443 {
444   Context::get()->state_manager->image_unbind_all();
445 }
446 
GPU_texture_generate_mipmap(GPUTexture * tex)447 void GPU_texture_generate_mipmap(GPUTexture *tex)
448 {
449   reinterpret_cast<Texture *>(tex)->generate_mipmap();
450 }
451 
452 /* Copy a texture content to a similar texture. Only Mip 0 is copied. */
GPU_texture_copy(GPUTexture * dst_,GPUTexture * src_)453 void GPU_texture_copy(GPUTexture *dst_, GPUTexture *src_)
454 {
455   Texture *src = reinterpret_cast<Texture *>(src_);
456   Texture *dst = reinterpret_cast<Texture *>(dst_);
457   src->copy_to(dst);
458 }
459 
GPU_texture_compare_mode(GPUTexture * tex_,bool use_compare)460 void GPU_texture_compare_mode(GPUTexture *tex_, bool use_compare)
461 {
462   Texture *tex = reinterpret_cast<Texture *>(tex_);
463   /* Only depth formats does support compare mode. */
464   BLI_assert(!(use_compare) || (tex->format_flag_get() & GPU_FORMAT_DEPTH));
465   SET_FLAG_FROM_TEST(tex->sampler_state, use_compare, GPU_SAMPLER_COMPARE);
466 }
467 
GPU_texture_filter_mode(GPUTexture * tex_,bool use_filter)468 void GPU_texture_filter_mode(GPUTexture *tex_, bool use_filter)
469 {
470   Texture *tex = reinterpret_cast<Texture *>(tex_);
471   /* Stencil and integer format does not support filtering. */
472   BLI_assert(!(use_filter) ||
473              !(tex->format_flag_get() & (GPU_FORMAT_STENCIL | GPU_FORMAT_INTEGER)));
474   SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
475 }
476 
GPU_texture_mipmap_mode(GPUTexture * tex_,bool use_mipmap,bool use_filter)477 void GPU_texture_mipmap_mode(GPUTexture *tex_, bool use_mipmap, bool use_filter)
478 {
479   Texture *tex = reinterpret_cast<Texture *>(tex_);
480   /* Stencil and integer format does not support filtering. */
481   BLI_assert(!(use_filter || use_mipmap) ||
482              !(tex->format_flag_get() & (GPU_FORMAT_STENCIL | GPU_FORMAT_INTEGER)));
483   SET_FLAG_FROM_TEST(tex->sampler_state, use_mipmap, GPU_SAMPLER_MIPMAP);
484   SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
485 }
486 
GPU_texture_anisotropic_filter(GPUTexture * tex_,bool use_aniso)487 void GPU_texture_anisotropic_filter(GPUTexture *tex_, bool use_aniso)
488 {
489   Texture *tex = reinterpret_cast<Texture *>(tex_);
490   /* Stencil and integer format does not support filtering. */
491   BLI_assert(!(use_aniso) ||
492              !(tex->format_flag_get() & (GPU_FORMAT_STENCIL | GPU_FORMAT_INTEGER)));
493   SET_FLAG_FROM_TEST(tex->sampler_state, use_aniso, GPU_SAMPLER_ANISO);
494 }
495 
GPU_texture_wrap_mode(GPUTexture * tex_,bool use_repeat,bool use_clamp)496 void GPU_texture_wrap_mode(GPUTexture *tex_, bool use_repeat, bool use_clamp)
497 {
498   Texture *tex = reinterpret_cast<Texture *>(tex_);
499   SET_FLAG_FROM_TEST(tex->sampler_state, use_repeat, GPU_SAMPLER_REPEAT);
500   SET_FLAG_FROM_TEST(tex->sampler_state, !use_clamp, GPU_SAMPLER_CLAMP_BORDER);
501 }
502 
GPU_texture_swizzle_set(GPUTexture * tex,const char swizzle[4])503 void GPU_texture_swizzle_set(GPUTexture *tex, const char swizzle[4])
504 {
505   reinterpret_cast<Texture *>(tex)->swizzle_set(swizzle);
506 }
507 
GPU_texture_free(GPUTexture * tex_)508 void GPU_texture_free(GPUTexture *tex_)
509 {
510   Texture *tex = reinterpret_cast<Texture *>(tex_);
511   tex->refcount--;
512 
513   if (tex->refcount < 0) {
514     fprintf(stderr, "GPUTexture: negative refcount\n");
515   }
516 
517   if (tex->refcount == 0) {
518     delete tex;
519   }
520 }
521 
GPU_texture_ref(GPUTexture * tex)522 void GPU_texture_ref(GPUTexture *tex)
523 {
524   reinterpret_cast<Texture *>(tex)->refcount++;
525 }
526 
GPU_texture_width(const GPUTexture * tex)527 int GPU_texture_width(const GPUTexture *tex)
528 {
529   return reinterpret_cast<const Texture *>(tex)->width_get();
530 }
531 
GPU_texture_height(const GPUTexture * tex)532 int GPU_texture_height(const GPUTexture *tex)
533 {
534   return reinterpret_cast<const Texture *>(tex)->height_get();
535 }
536 
GPU_texture_orig_width(const GPUTexture * tex)537 int GPU_texture_orig_width(const GPUTexture *tex)
538 {
539   return reinterpret_cast<const Texture *>(tex)->src_w;
540 }
541 
GPU_texture_orig_height(const GPUTexture * tex)542 int GPU_texture_orig_height(const GPUTexture *tex)
543 {
544   return reinterpret_cast<const Texture *>(tex)->src_h;
545 }
546 
GPU_texture_orig_size_set(GPUTexture * tex_,int w,int h)547 void GPU_texture_orig_size_set(GPUTexture *tex_, int w, int h)
548 {
549   Texture *tex = reinterpret_cast<Texture *>(tex_);
550   tex->src_w = w;
551   tex->src_h = h;
552 }
553 
GPU_texture_format(const GPUTexture * tex)554 eGPUTextureFormat GPU_texture_format(const GPUTexture *tex)
555 {
556   return reinterpret_cast<const Texture *>(tex)->format_get();
557 }
558 
GPU_texture_depth(const GPUTexture * tex)559 bool GPU_texture_depth(const GPUTexture *tex)
560 {
561   return (reinterpret_cast<const Texture *>(tex)->format_flag_get() & GPU_FORMAT_DEPTH) != 0;
562 }
563 
GPU_texture_stencil(const GPUTexture * tex)564 bool GPU_texture_stencil(const GPUTexture *tex)
565 {
566   return (reinterpret_cast<const Texture *>(tex)->format_flag_get() & GPU_FORMAT_STENCIL) != 0;
567 }
568 
GPU_texture_integer(const GPUTexture * tex)569 bool GPU_texture_integer(const GPUTexture *tex)
570 {
571   return (reinterpret_cast<const Texture *>(tex)->format_flag_get() & GPU_FORMAT_INTEGER) != 0;
572 }
573 
GPU_texture_cube(const GPUTexture * tex)574 bool GPU_texture_cube(const GPUTexture *tex)
575 {
576   return (reinterpret_cast<const Texture *>(tex)->type_get() & GPU_TEXTURE_CUBE) != 0;
577 }
578 
GPU_texture_array(const GPUTexture * tex)579 bool GPU_texture_array(const GPUTexture *tex)
580 {
581   return (reinterpret_cast<const Texture *>(tex)->type_get() & GPU_TEXTURE_ARRAY) != 0;
582 }
583 
584 /* TODO remove */
GPU_texture_opengl_bindcode(const GPUTexture * tex)585 int GPU_texture_opengl_bindcode(const GPUTexture *tex)
586 {
587   return reinterpret_cast<const Texture *>(tex)->gl_bindcode_get();
588 }
589 
GPU_texture_get_mipmap_size(GPUTexture * tex,int lvl,int * r_size)590 void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *r_size)
591 {
592   return reinterpret_cast<Texture *>(tex)->mip_size_get(lvl, r_size);
593 }
594 
595 /** \} */
596 
597 /* -------------------------------------------------------------------- */
598 /** \name GPU Sampler Objects
599  *
600  * Simple wrapper around opengl sampler objects.
601  * Override texture sampler state for one sampler unit only.
602  * \{ */
603 
604 /* Update user defined sampler states. */
GPU_samplers_update(void)605 void GPU_samplers_update(void)
606 {
607   GPUBackend::get()->samplers_update();
608 }
609 
610 /** \} */
611