Blender V4.5
gpu_py_texture.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
13
14#include <Python.h>
15
16#include "BLI_math_base.h"
17#include "BLI_string.h"
18
19#include "DNA_image_types.h"
20
21#include "GPU_context.hh"
22#include "GPU_texture.hh"
23
24#include "BKE_image.hh"
25
27#include "../generic/python_compat.hh" /* IWYU pragma: keep. */
28
29#include "gpu_py.hh"
30#include "gpu_py_buffer.hh"
31
32#include "gpu_py_texture.hh" /* own include */
33
34/* -------------------------------------------------------------------- */
37
39 {GPU_RGBA8UI, "RGBA8UI"},
40 {GPU_RGBA8I, "RGBA8I"},
41 {GPU_RGBA8, "RGBA8"},
42 {GPU_RGBA32UI, "RGBA32UI"},
43 {GPU_RGBA32I, "RGBA32I"},
44 {GPU_RGBA32F, "RGBA32F"},
45 {GPU_RGBA16UI, "RGBA16UI"},
46 {GPU_RGBA16I, "RGBA16I"},
47 {GPU_RGBA16F, "RGBA16F"},
48 {GPU_RGBA16, "RGBA16"},
49 {GPU_RG8UI, "RG8UI"},
50 {GPU_RG8I, "RG8I"},
51 {GPU_RG8, "RG8"},
52 {GPU_RG32UI, "RG32UI"},
53 {GPU_RG32I, "RG32I"},
54 {GPU_RG32F, "RG32F"},
55 {GPU_RG16UI, "RG16UI"},
56 {GPU_RG16I, "RG16I"},
57 {GPU_RG16F, "RG16F"},
58 {GPU_RG16, "RG16"},
59 {GPU_R8UI, "R8UI"},
60 {GPU_R8I, "R8I"},
61 {GPU_R8, "R8"},
62 {GPU_R32UI, "R32UI"},
63 {GPU_R32I, "R32I"},
64 {GPU_R32F, "R32F"},
65 {GPU_R16UI, "R16UI"},
66 {GPU_R16I, "R16I"},
67 {GPU_R16F, "R16F"},
68 {GPU_R16, "R16"},
69 {GPU_R11F_G11F_B10F, "R11F_G11F_B10F"},
70 {GPU_DEPTH32F_STENCIL8, "DEPTH32F_STENCIL8"},
71 {GPU_DEPTH24_STENCIL8, "DEPTH24_STENCIL8"},
72 {GPU_SRGB8_A8, "SRGB8_A8"},
73 {GPU_RGB16F, "RGB16F"},
74 {GPU_SRGB8_A8_DXT1, "SRGB8_A8_DXT1"},
75 {GPU_SRGB8_A8_DXT3, "SRGB8_A8_DXT3"},
76 {GPU_SRGB8_A8_DXT5, "SRGB8_A8_DXT5"},
77 {GPU_RGBA8_DXT1, "RGBA8_DXT1"},
78 {GPU_RGBA8_DXT3, "RGBA8_DXT3"},
79 {GPU_RGBA8_DXT5, "RGBA8_DXT5"},
80 {GPU_DEPTH_COMPONENT32F, "DEPTH_COMPONENT32F"},
81 {GPU_DEPTH_COMPONENT24, "DEPTH_COMPONENT24"},
82 {GPU_DEPTH_COMPONENT16, "DEPTH_COMPONENT16"},
83 {0, nullptr},
84};
85
87{
88 if (UNLIKELY(bpygpu_tex->tex == nullptr)) {
89 PyErr_SetString(PyExc_ReferenceError,
91 "GPU texture was freed, no further access is valid"
92#else
93 "GPU texture: internal error"
94#endif
95 );
96
97 return -1;
98 }
99 return 0;
100}
101
102#define BPYGPU_TEXTURE_CHECK_OBJ(bpygpu) \
103 { \
104 if (UNLIKELY(pygpu_texture_valid_check(bpygpu) == -1)) { \
105 return nullptr; \
106 } \
107 } \
108 ((void)0)
109
111
112/* -------------------------------------------------------------------- */
115
116static PyObject *pygpu_texture__tp_new(PyTypeObject * /*self*/, PyObject *args, PyObject *kwds)
117{
119
120 PyObject *py_size;
121 int size[3] = {1, 1, 1};
122 int layers = 0;
123 int is_cubemap = false;
124 PyC_StringEnum pygpu_textureformat = {pygpu_textureformat_items, GPU_RGBA8};
125 BPyGPUBuffer *pybuffer_obj = nullptr;
126 char err_out[256] = "unknown error. See console";
127
128 static const char *_keywords[] = {"size", "layers", "is_cubemap", "format", "data", nullptr};
129 static _PyArg_Parser _parser = {
131 "O" /* `size` */
132 "|$" /* Optional keyword only arguments. */
133 "i" /* `layers` */
134 "p" /* `is_cubemap` */
135 "O&" /* `format` */
136 "O!" /* `data` */
137 ":GPUTexture.__new__",
138 _keywords,
139 nullptr,
140 };
141 if (!_PyArg_ParseTupleAndKeywordsFast(args,
142 kwds,
143 &_parser,
144 &py_size,
145 &layers,
146 &is_cubemap,
148 &pygpu_textureformat,
150 &pybuffer_obj))
151 {
152 return nullptr;
153 }
154
155 int len = 1;
156 if (PySequence_Check(py_size)) {
157 len = PySequence_Size(py_size);
158 if ((len < 1) || (len > 3)) {
159 PyErr_Format(PyExc_ValueError,
160 "GPUTexture.__new__: \"size\" must be between 1 and 3 in length (got %d)",
161 len);
162 return nullptr;
163 }
164 if (PyC_AsArray(size, sizeof(*size), py_size, len, &PyLong_Type, "GPUTexture.__new__") == -1) {
165 return nullptr;
166 }
167 }
168 else if (PyLong_Check(py_size)) {
169 size[0] = PyLong_AsLong(py_size);
170 }
171 else {
172 PyErr_SetString(PyExc_ValueError, "GPUTexture.__new__: Expected an int or tuple as first arg");
173 return nullptr;
174 }
175
176 void *data = nullptr;
177 if (pybuffer_obj) {
178 if (pybuffer_obj->format != GPU_DATA_FLOAT) {
179 PyErr_SetString(PyExc_ValueError,
180 "GPUTexture.__new__: Only Buffer of format `FLOAT` is currently supported");
181 return nullptr;
182 }
183
184 int component_len = GPU_texture_component_len(
185 eGPUTextureFormat(pygpu_textureformat.value_found));
186 int component_size_expected = sizeof(float);
187 size_t data_space_expected = size_t(size[0]) * size[1] * size[2] * max_ii(1, layers) *
188 component_len * component_size_expected;
189 if (is_cubemap) {
190 data_space_expected *= 6 * size[0];
191 }
192
193 if (bpygpu_Buffer_size(pybuffer_obj) < data_space_expected) {
194 PyErr_SetString(PyExc_ValueError, "GPUTexture.__new__: Buffer size smaller than requested");
195 return nullptr;
196 }
197 data = pybuffer_obj->buf.as_void;
198 }
199
200 GPUTexture *tex = nullptr;
201 if (is_cubemap && len != 1) {
202 STRNCPY(err_out,
203 "In cubemaps the same dimension represents height, width and depth. No tuple needed");
204 }
205 else if (size[0] < 1 || size[1] < 1 || size[2] < 1) {
206 STRNCPY(err_out, "Values less than 1 are not allowed in dimensions");
207 }
208 else if (layers && len == 3) {
209 STRNCPY(err_out, "3D textures have no layers");
210 }
211 else if (!GPU_context_active_get()) {
212 STRNCPY(err_out, "No active GPU context found");
213 }
214 else {
215 const char *name = "python_texture";
217 if (is_cubemap) {
218 if (layers) {
220 size[0],
221 layers,
222 1,
223 eGPUTextureFormat(pygpu_textureformat.value_found),
224 usage,
225 static_cast<const float *>(data));
226 }
227 else {
228 tex = GPU_texture_create_cube(name,
229 size[0],
230 1,
231 eGPUTextureFormat(pygpu_textureformat.value_found),
232 usage,
233 static_cast<const float *>(data));
234 }
235 }
236 else if (layers) {
237 if (len == 2) {
239 size[0],
240 size[1],
241 layers,
242 1,
243 eGPUTextureFormat(pygpu_textureformat.value_found),
244 usage,
245 static_cast<const float *>(data));
246 }
247 else {
249 size[0],
250 layers,
251 1,
252 eGPUTextureFormat(pygpu_textureformat.value_found),
253 usage,
254 static_cast<const float *>(data));
255 }
256 }
257 else if (len == 3) {
258 tex = GPU_texture_create_3d(name,
259 size[0],
260 size[1],
261 size[2],
262 1,
263 eGPUTextureFormat(pygpu_textureformat.value_found),
264 usage,
265 data);
266 }
267 else if (len == 2) {
268 tex = GPU_texture_create_2d(name,
269 size[0],
270 size[1],
271 1,
272 eGPUTextureFormat(pygpu_textureformat.value_found),
273 usage,
274 static_cast<const float *>(data));
275 }
276 else {
277 tex = GPU_texture_create_1d(name,
278 size[0],
279 1,
280 eGPUTextureFormat(pygpu_textureformat.value_found),
281 usage,
282 static_cast<const float *>(data));
283 }
284 }
285
286 if (tex == nullptr) {
287 PyErr_Format(PyExc_RuntimeError, "gpu.texture.new(...) failed with '%s'", err_out);
288 return nullptr;
289 }
290
291 return BPyGPUTexture_CreatePyObject(tex, false);
292}
293
295 /* Wrap. */
296 pygpu_texture_width_doc,
297 "Width of the texture.\n"
298 "\n"
299 ":type: int");
300static PyObject *pygpu_texture_width_get(BPyGPUTexture *self, void * /*type*/)
301{
303 return PyLong_FromLong(GPU_texture_width(self->tex));
304}
305
307 /* Wrap. */
308 pygpu_texture_height_doc,
309 "Height of the texture.\n"
310 "\n"
311 ":type: int");
312static PyObject *pygpu_texture_height_get(BPyGPUTexture *self, void * /*type*/)
313{
315 return PyLong_FromLong(GPU_texture_height(self->tex));
316}
317
319 /* Wrap. */
320 pygpu_texture_format_doc,
321 "Format of the texture.\n"
322 "\n"
323 ":type: str");
330
332 /* Wrap. */
333 pygpu_texture_clear_doc,
334 ".. method:: clear(format='FLOAT', value=(0.0, 0.0, 0.0, 1.0))\n"
335 "\n"
336 " Fill texture with specific value.\n"
337 "\n"
338 " :arg format: The format that describes the content of a single item.\n"
339 " Possible values are `FLOAT`, `INT`, `UINT`, `UBYTE`, `UINT_24_8` and `10_11_11_REV`.\n"
340 " :type format: str\n"
341 " :arg value: Sequence each representing the value to fill. Sizes 1..4 are supported.\n"
342 " :type value: Sequence[float]\n");
343static PyObject *pygpu_texture_clear(BPyGPUTexture *self, PyObject *args, PyObject *kwds)
344{
346 PyC_StringEnum pygpu_dataformat = {bpygpu_dataformat_items};
347 union {
348 int i[4];
349 float f[4];
350 char c[4];
351 } values;
352
353 PyObject *py_values;
354
355 static const char *_keywords[] = {"format", "value", nullptr};
356 static _PyArg_Parser _parser = {
358 "$" /* Keyword only arguments. */
359 "O&" /* `format` */
360 "O" /* `value` */
361 ":clear",
362 _keywords,
363 nullptr,
364 };
365 if (!_PyArg_ParseTupleAndKeywordsFast(
366 args, kwds, &_parser, PyC_ParseStringEnum, &pygpu_dataformat, &py_values))
367 {
368 return nullptr;
369 }
370
371 int shape = PySequence_Size(py_values);
372 if (shape == -1) {
373 return nullptr;
374 }
375
376 if (shape > 4) {
377 PyErr_SetString(PyExc_AttributeError, "too many dimensions, max is 4");
378 return nullptr;
379 }
380
381 if (shape != 1 && ELEM(pygpu_dataformat.value_found, GPU_DATA_UINT_24_8, GPU_DATA_10_11_11_REV))
382 {
383 PyErr_SetString(PyExc_AttributeError,
384 "`UINT_24_8` and `10_11_11_REV` only support single values");
385 return nullptr;
386 }
387
388 memset(&values, 0, sizeof(values));
389 if (PyC_AsArray(&values,
390 (pygpu_dataformat.value_found == GPU_DATA_FLOAT) ? sizeof(*values.f) :
391 sizeof(*values.i),
392 py_values,
393 shape,
394 (pygpu_dataformat.value_found == GPU_DATA_FLOAT) ? &PyFloat_Type : &PyLong_Type,
395 "clear") == -1)
396 {
397 return nullptr;
398 }
399
400 if (pygpu_dataformat.value_found == GPU_DATA_UBYTE) {
401 /* Convert to byte. */
402 values.c[0] = values.i[0];
403 values.c[1] = values.i[1];
404 values.c[2] = values.i[2];
405 values.c[3] = values.i[3];
406 }
407
408 GPU_texture_clear(self->tex, eGPUDataFormat(pygpu_dataformat.value_found), &values);
409 Py_RETURN_NONE;
410}
411
413 /* Wrap. */
414 pygpu_texture_read_doc,
415 ".. method:: read()\n"
416 "\n"
417 " Creates a buffer with the value of all pixels.\n"
418 "\n");
420{
422 eGPUTextureFormat tex_format = GPU_texture_format(self->tex);
423
424 /* #GPU_texture_read is restricted in combining 'data_format' with 'tex_format'.
425 * So choose data_format here. */
426 eGPUDataFormat best_data_format;
427 switch (tex_format) {
431 best_data_format = GPU_DATA_FLOAT;
432 break;
435 best_data_format = GPU_DATA_UINT_24_8;
436 break;
437 case GPU_R8UI:
438 case GPU_R16UI:
439 case GPU_RG16UI:
440 case GPU_R32UI:
441 best_data_format = GPU_DATA_UINT;
442 break;
443 case GPU_RG16I:
444 case GPU_R16I:
445 best_data_format = GPU_DATA_INT;
446 break;
447 case GPU_R8:
448 case GPU_RG8:
449 case GPU_RGBA8:
450 case GPU_RGBA8UI:
451 case GPU_SRGB8_A8:
452 best_data_format = GPU_DATA_UBYTE;
453 break;
455 best_data_format = GPU_DATA_10_11_11_REV;
456 break;
457 default:
458 best_data_format = GPU_DATA_FLOAT;
459 break;
460 }
461
462 void *buf = GPU_texture_read(self->tex, best_data_format, 0);
463 const Py_ssize_t shape[3] = {GPU_texture_height(self->tex),
465 Py_ssize_t(GPU_texture_component_len(tex_format))};
466
467 int shape_len = (shape[2] == 1) ? 2 : 3;
468 return (PyObject *)BPyGPU_Buffer_CreatePyObject(best_data_format, shape, shape_len, buf);
469}
470
471#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
473 /* Wrap. */
474 pygpu_texture_free_doc,
475 ".. method:: free()\n"
476 "\n"
477 " Free the texture object.\n"
478 " The texture object will no longer be accessible.\n");
479static PyObject *pygpu_texture_free(BPyGPUTexture *self)
480{
482
484 self->tex = nullptr;
485 Py_RETURN_NONE;
486}
487#endif
488
490{
491 if (self->tex) {
492#ifndef GPU_NO_USE_PY_REFERENCES
493 GPU_texture_py_reference_set(self->tex, nullptr);
494#endif
496 }
497 Py_TYPE(self)->tp_free((PyObject *)self);
498}
499
500static PyGetSetDef pygpu_texture__tp_getseters[] = {
501 {"width", (getter)pygpu_texture_width_get, (setter) nullptr, pygpu_texture_width_doc, nullptr},
502 {"height",
504 (setter) nullptr,
505 pygpu_texture_height_doc,
506 nullptr},
507 {"format",
509 (setter) nullptr,
510 pygpu_texture_format_doc,
511 nullptr},
512 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
513};
514
515#ifdef __GNUC__
516# ifdef __clang__
517# pragma clang diagnostic push
518# pragma clang diagnostic ignored "-Wcast-function-type"
519# else
520# pragma GCC diagnostic push
521# pragma GCC diagnostic ignored "-Wcast-function-type"
522# endif
523#endif
524
525static PyMethodDef pygpu_texture__tp_methods[] = {
526 {"clear",
527 (PyCFunction)pygpu_texture_clear,
528 METH_VARARGS | METH_KEYWORDS,
529 pygpu_texture_clear_doc},
530 {"read", (PyCFunction)pygpu_texture_read, METH_NOARGS, pygpu_texture_read_doc},
531#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
532 {"free", (PyCFunction)pygpu_texture_free, METH_NOARGS, pygpu_texture_free_doc},
533#endif
534 {nullptr, nullptr, 0, nullptr},
535};
536
537#ifdef __GNUC__
538# ifdef __clang__
539# pragma clang diagnostic pop
540# else
541# pragma GCC diagnostic pop
542# endif
543#endif
544
546 /* Wrap. */
547 pygpu_texture__tp_doc,
548 ".. class:: GPUTexture(size, layers=0, is_cubemap=False, format='RGBA8', data=None)\n"
549 "\n"
550 " This object gives access to off GPU textures.\n"
551 "\n"
552 " :arg size: Dimensions of the texture 1D, 2D, 3D or cubemap.\n"
553 " :type size: int | Sequence[int]\n"
554 " :arg layers: Number of layers in texture array or number of cubemaps in cubemap array\n"
555 " :type layers: int\n"
556 " :arg is_cubemap: Indicates the creation of a cubemap texture.\n"
557 " :type is_cubemap: int\n"
558 " :arg format: Internal data format inside GPU memory. Possible values are:\n"
559 " `RGBA8UI`,\n"
560 " `RGBA8I`,\n"
561 " `RGBA8`,\n"
562 " `RGBA32UI`,\n"
563 " `RGBA32I`,\n"
564 " `RGBA32F`,\n"
565 " `RGBA16UI`,\n"
566 " `RGBA16I`,\n"
567 " `RGBA16F`,\n"
568 " `RGBA16`,\n"
569 " `RG8UI`,\n"
570 " `RG8I`,\n"
571 " `RG8`,\n"
572 " `RG32UI`,\n"
573 " `RG32I`,\n"
574 " `RG32F`,\n"
575 " `RG16UI`,\n"
576 " `RG16I`,\n"
577 " `RG16F`,\n"
578 " `RG16`,\n"
579 " `R8UI`,\n"
580 " `R8I`,\n"
581 " `R8`,\n"
582 " `R32UI`,\n"
583 " `R32I`,\n"
584 " `R32F`,\n"
585 " `R16UI`,\n"
586 " `R16I`,\n"
587 " `R16F`,\n"
588 " `R16`,\n"
589 " `R11F_G11F_B10F`,\n"
590 " `DEPTH32F_STENCIL8`,\n"
591 " `DEPTH24_STENCIL8`,\n"
592 " `SRGB8_A8`,\n"
593 " `RGB16F`,\n"
594 " `SRGB8_A8_DXT1`,\n"
595 " `SRGB8_A8_DXT3`,\n"
596 " `SRGB8_A8_DXT5`,\n"
597 " `RGBA8_DXT1`,\n"
598 " `RGBA8_DXT3`,\n"
599 " `RGBA8_DXT5`,\n"
600 " `DEPTH_COMPONENT32F`,\n"
601 " `DEPTH_COMPONENT24`,\n"
602 " `DEPTH_COMPONENT16`,\n"
603 " :type format: str\n"
604 " :arg data: Buffer object to fill the texture.\n"
605 " :type data: :class:`gpu.types.Buffer`\n");
606PyTypeObject BPyGPUTexture_Type = {
607 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
608 /*tp_name*/ "GPUTexture",
609 /*tp_basicsize*/ sizeof(BPyGPUTexture),
610 /*tp_itemsize*/ 0,
611 /*tp_dealloc*/ (destructor)BPyGPUTexture__tp_dealloc,
612 /*tp_vectorcall_offset*/ 0,
613 /*tp_getattr*/ nullptr,
614 /*tp_setattr*/ nullptr,
615 /*tp_as_async*/ nullptr,
616 /*tp_repr*/ nullptr,
617 /*tp_as_number*/ nullptr,
618 /*tp_as_sequence*/ nullptr,
619 /*tp_as_mapping*/ nullptr,
620 /*tp_hash*/ nullptr,
621 /*tp_call*/ nullptr,
622 /*tp_str*/ nullptr,
623 /*tp_getattro*/ nullptr,
624 /*tp_setattro*/ nullptr,
625 /*tp_as_buffer*/ nullptr,
626 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
627 /*tp_doc*/ pygpu_texture__tp_doc,
628 /*tp_traverse*/ nullptr,
629 /*tp_clear*/ nullptr,
630 /*tp_richcompare*/ nullptr,
631 /*tp_weaklistoffset*/ 0,
632 /*tp_iter*/ nullptr,
633 /*tp_iternext*/ nullptr,
634 /*tp_methods*/ pygpu_texture__tp_methods,
635 /*tp_members*/ nullptr,
636 /*tp_getset*/ pygpu_texture__tp_getseters,
637 /*tp_base*/ nullptr,
638 /*tp_dict*/ nullptr,
639 /*tp_descr_get*/ nullptr,
640 /*tp_descr_set*/ nullptr,
641 /*tp_dictoffset*/ 0,
642 /*tp_init*/ nullptr,
643 /*tp_alloc*/ nullptr,
644 /*tp_new*/ pygpu_texture__tp_new,
645 /*tp_free*/ nullptr,
646 /*tp_is_gc*/ nullptr,
647 /*tp_bases*/ nullptr,
648 /*tp_mro*/ nullptr,
649 /*tp_cache*/ nullptr,
650 /*tp_subclasses*/ nullptr,
651 /*tp_weaklist*/ nullptr,
652 /*tp_del*/ nullptr,
653 /*tp_version_tag*/ 0,
654 /*tp_finalize*/ nullptr,
655 /*tp_vectorcall*/ nullptr,
656};
657
659
660/* -------------------------------------------------------------------- */
663
665 /* Wrap. */
666 pygpu_texture_from_image_doc,
667 ".. function:: from_image(image)\n"
668 "\n"
669 " Get GPUTexture corresponding to an Image datablock. The GPUTexture memory is "
670 "shared with Blender.\n"
671 " Note: Colors read from the texture will be in scene linear color space and have "
672 "premultiplied or straight alpha matching the image alpha mode.\n"
673 "\n"
674 " :arg image: The Image datablock.\n"
675 " :type image: :class:`bpy.types.Image`\n"
676 " :return: The GPUTexture used by the image.\n"
677 " :rtype: :class:`gpu.types.GPUTexture`\n");
678static PyObject *pygpu_texture_from_image(PyObject * /*self*/, PyObject *arg)
679{
680 Image *ima = static_cast<Image *>(PyC_RNA_AsPointer(arg, "Image"));
681 if (ima == nullptr) {
682 return nullptr;
683 }
684
685 ImageUser iuser;
686 BKE_imageuser_default(&iuser);
687 GPUTexture *tex = BKE_image_get_gpu_texture(ima, &iuser);
688
689 return BPyGPUTexture_CreatePyObject(tex, true);
690}
691
692static PyMethodDef pygpu_texture__m_methods[] = {
693 {"from_image", (PyCFunction)pygpu_texture_from_image, METH_O, pygpu_texture_from_image_doc},
694 {nullptr, nullptr, 0, nullptr},
695};
696
698 /* Wrap. */
699 pygpu_texture__m_doc,
700 "This module provides utils for textures.");
701static PyModuleDef pygpu_texture_module_def = {
702 /*m_base*/ PyModuleDef_HEAD_INIT,
703 /*m_name*/ "gpu.texture",
704 /*m_doc*/ pygpu_texture__m_doc,
705 /*m_size*/ 0,
706 /*m_methods*/ pygpu_texture__m_methods,
707 /*m_slots*/ nullptr,
708 /*m_traverse*/ nullptr,
709 /*m_clear*/ nullptr,
710 /*m_free*/ nullptr,
711};
712
714
715/* -------------------------------------------------------------------- */
718
719int bpygpu_ParseTexture(PyObject *o, void *p)
720{
721 if (o == Py_None) {
722 *(GPUTexture **)p = nullptr;
723 return 1;
724 }
725
726 if (!BPyGPUTexture_Check(o)) {
727 PyErr_Format(
728 PyExc_ValueError, "expected a texture or None object, got %s", Py_TYPE(o)->tp_name);
729 return 0;
730 }
731
733 return 0;
734 }
735
736 *(GPUTexture **)p = ((BPyGPUTexture *)o)->tex;
737 return 1;
738}
739
741{
742 PyObject *submodule;
743 submodule = PyModule_Create(&pygpu_texture_module_def);
744
745 return submodule;
746}
747
749
750/* -------------------------------------------------------------------- */
753
754PyObject *BPyGPUTexture_CreatePyObject(GPUTexture *tex, bool shared_reference)
755{
757
758 if (shared_reference) {
759#ifndef GPU_NO_USE_PY_REFERENCES
760 void **ref = GPU_texture_py_reference_get(tex);
761 if (ref) {
762 /* Retrieve BPyGPUTexture reference. */
764 BLI_assert(self->tex == tex);
765 Py_INCREF(self);
766 return (PyObject *)self;
767 }
768#endif
769
770 GPU_texture_ref(tex);
771 }
772
773 self = PyObject_New(BPyGPUTexture, &BPyGPUTexture_Type);
774 self->tex = tex;
775
776#ifndef GPU_NO_USE_PY_REFERENCES
778 GPU_texture_py_reference_set(tex, (void **)&self->tex);
779#endif
780
781 return (PyObject *)self;
782}
783
785
786#undef BPYGPU_TEXTURE_CHECK_OBJ
void BKE_imageuser_default(ImageUser *iuser)
GPUTexture * BKE_image_get_gpu_texture(Image *image, ImageUser *iuser)
Definition image_gpu.cc:486
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE int max_ii(int a, int b)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define UNLIKELY(x)
#define ELEM(...)
#define POINTER_OFFSET(v, ofs)
GPUContext * GPU_context_active_get()
int GPU_texture_height(const GPUTexture *texture)
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
GPUTexture * GPU_texture_create_1d(const char *name, int width, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
int GPU_texture_width(const GPUTexture *texture)
void GPU_texture_clear(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
void GPU_texture_ref(GPUTexture *texture)
void ** GPU_texture_py_reference_get(GPUTexture *texture)
void * GPU_texture_read(GPUTexture *texture, eGPUDataFormat data_format, int mip_level)
void GPU_texture_py_reference_set(GPUTexture *texture, void **py_ref)
GPUTexture * GPU_texture_create_cube_array(const char *name, int width, int layer_len, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
eGPUDataFormat
@ GPU_DATA_UINT_24_8
@ GPU_DATA_INT
@ GPU_DATA_10_11_11_REV
@ GPU_DATA_UBYTE
@ GPU_DATA_UINT
@ GPU_DATA_FLOAT
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_GENERAL
GPUTexture * GPU_texture_create_2d_array(const char *name, int width, int height, int layer_len, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
GPUTexture * GPU_texture_create_3d(const char *name, int width, int height, int depth, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const void *data)
eGPUTextureFormat
@ GPU_R16UI
@ GPU_RG16F
@ GPU_DEPTH32F_STENCIL8
@ GPU_R32F
@ GPU_R16I
@ GPU_SRGB8_A8
@ GPU_DEPTH24_STENCIL8
@ GPU_R32I
@ GPU_RG8UI
@ GPU_R16F
@ GPU_SRGB8_A8_DXT5
@ GPU_RG8I
@ GPU_RG16I
@ GPU_RG32UI
@ GPU_RGBA32F
@ GPU_RGBA16F
@ GPU_RG8
@ GPU_RG32I
@ GPU_SRGB8_A8_DXT1
@ GPU_RG16
@ GPU_RGBA32UI
@ GPU_R8I
@ GPU_R16
@ GPU_RG16UI
@ GPU_RGBA8I
@ GPU_RGBA8_DXT1
@ GPU_RGBA8UI
@ GPU_RGBA16UI
@ GPU_RGBA16I
@ GPU_R8UI
@ GPU_RGBA16
@ GPU_SRGB8_A8_DXT3
@ GPU_RGBA8_DXT3
@ GPU_RG32F
@ GPU_R8
@ GPU_DEPTH_COMPONENT24
@ GPU_RGB16F
@ GPU_R32UI
@ GPU_RGBA32I
@ GPU_RGBA8_DXT5
@ GPU_DEPTH_COMPONENT32F
@ GPU_DEPTH_COMPONENT16
@ GPU_R11F_G11F_B10F
@ GPU_RGBA8
GPUTexture * GPU_texture_create_cube(const char *name, int width, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
GPUTexture * GPU_texture_create_1d_array(const char *name, int width, int layer_len, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
size_t GPU_texture_component_len(eGPUTextureFormat format)
eGPUTextureFormat GPU_texture_format(const GPUTexture *texture)
BMesh const char void * data
PyObject * self
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
#define offsetof(t, d)
PyC_StringEnumItems bpygpu_dataformat_items[]
Definition gpu_py.cc:40
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
Definition gpu_py.hh:20
PyTypeObject BPyGPU_BufferType
BPyGPUBuffer * BPyGPU_Buffer_CreatePyObject(const int format, const Py_ssize_t *shape, const int shape_len, void *buffer)
size_t bpygpu_Buffer_size(BPyGPUBuffer *buffer)
#define BPYGPU_USE_GPUOBJ_FREE_METHOD
PyTypeObject BPyGPUTexture_Type
static PyObject * pygpu_texture_width_get(BPyGPUTexture *self, void *)
PyObject * BPyGPUTexture_CreatePyObject(GPUTexture *tex, bool shared_reference)
static PyObject * pygpu_texture_clear(BPyGPUTexture *self, PyObject *args, PyObject *kwds)
PyObject * bpygpu_texture_init()
PyDoc_STRVAR(pygpu_texture_width_doc, "Width of the texture.\n" "\n" ":type: int")
static void BPyGPUTexture__tp_dealloc(BPyGPUTexture *self)
static int pygpu_texture_valid_check(BPyGPUTexture *bpygpu_tex)
static PyGetSetDef pygpu_texture__tp_getseters[]
#define BPYGPU_TEXTURE_CHECK_OBJ(bpygpu)
static PyObject * pygpu_texture_from_image(PyObject *, PyObject *arg)
static PyObject * pygpu_texture__tp_new(PyTypeObject *, PyObject *args, PyObject *kwds)
static PyObject * pygpu_texture_height_get(BPyGPUTexture *self, void *)
int bpygpu_ParseTexture(PyObject *o, void *p)
static PyObject * pygpu_texture_read(BPyGPUTexture *self)
const PyC_StringEnumItems pygpu_textureformat_items[]
static PyMethodDef pygpu_texture__m_methods[]
static PyMethodDef pygpu_texture__tp_methods[]
static PyModuleDef pygpu_texture_module_def
static PyObject * pygpu_texture_format_get(BPyGPUTexture *self, void *)
#define BPyGPUTexture_Check(v)
format
void * PyC_RNA_AsPointer(PyObject *value, const char *type_name)
int PyC_ParseStringEnum(PyObject *o, void *p)
int PyC_AsArray(void *array, const size_t array_item_size, PyObject *value, const Py_ssize_t length, const PyTypeObject *type, const char *error_prefix)
const char * PyC_StringEnum_FindIDFromValue(const PyC_StringEnumItems *items, const int value)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
union BPyGPUBuffer::@156235326231167136112107117153043033043051263025 buf
PyObject_HEAD GPUTexture * tex
i
Definition text_draw.cc:230
uint len