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