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