1/**************************************************************************/
2/* texture_rd.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "texture_rd.h"
32
33////////////////////////////////////////////////////////////////////////////
34// Texture2DRD
35
36void Texture2DRD::_bind_methods() {
37 ClassDB::bind_method(D_METHOD("set_texture_rd_rid", "texture_rd_rid"), &Texture2DRD::set_texture_rd_rid);
38 ClassDB::bind_method(D_METHOD("get_texture_rd_rid"), &Texture2DRD::get_texture_rd_rid);
39
40 ADD_PROPERTY(PropertyInfo(Variant::RID, "texture_rd_rid"), "set_texture_rd_rid", "get_texture_rd_rid");
41}
42
43int Texture2DRD::get_width() const {
44 return size.width;
45}
46
47int Texture2DRD::get_height() const {
48 return size.height;
49}
50
51RID Texture2DRD::get_rid() const {
52 if (texture_rid.is_null()) {
53 // We are in trouble, create something temporary.
54 texture_rid = RenderingServer::get_singleton()->texture_2d_placeholder_create();
55 }
56
57 return texture_rid;
58}
59
60bool Texture2DRD::has_alpha() const {
61 return false;
62}
63
64Ref<Image> Texture2DRD::get_image() const {
65 ERR_FAIL_NULL_V(RS::get_singleton(), Ref<Image>());
66 if (texture_rid.is_valid()) {
67 return RS::get_singleton()->texture_2d_get(texture_rid);
68 } else {
69 return Ref<Image>();
70 }
71}
72
73void Texture2DRD::set_texture_rd_rid(RID p_texture_rd_rid) {
74 ERR_FAIL_NULL(RS::get_singleton());
75
76 if (p_texture_rd_rid.is_valid()) {
77 ERR_FAIL_NULL(RD::get_singleton());
78 ERR_FAIL_COND(!RD::get_singleton()->texture_is_valid(p_texture_rd_rid));
79
80 RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_texture_rd_rid);
81 ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_2D);
82 ERR_FAIL_COND(tf.depth > 1);
83 ERR_FAIL_COND(tf.array_layers > 1);
84
85 size.width = tf.width;
86 size.height = tf.height;
87
88 texture_rd_rid = p_texture_rd_rid;
89
90 if (texture_rid.is_valid()) {
91 RS::get_singleton()->texture_replace(texture_rid, RS::get_singleton()->texture_rd_create(p_texture_rd_rid));
92 } else {
93 texture_rid = RS::get_singleton()->texture_rd_create(p_texture_rd_rid);
94 }
95
96 notify_property_list_changed();
97 emit_changed();
98 } else if (texture_rid.is_valid()) {
99 RS::get_singleton()->free(texture_rid);
100 texture_rid = RID();
101 size = Size2i();
102
103 notify_property_list_changed();
104 emit_changed();
105 }
106}
107
108RID Texture2DRD::get_texture_rd_rid() const {
109 return texture_rd_rid;
110}
111
112Texture2DRD::Texture2DRD() {
113 size = Size2i();
114}
115
116Texture2DRD::~Texture2DRD() {
117 if (texture_rid.is_valid()) {
118 ERR_FAIL_NULL(RS::get_singleton());
119 RS::get_singleton()->free(texture_rid);
120 texture_rid = RID();
121 }
122}
123
124////////////////////////////////////////////////////////////////////////////
125// TextureLayeredRD
126
127void TextureLayeredRD::_bind_methods() {
128 ClassDB::bind_method(D_METHOD("set_texture_rd_rid", "texture_rd_rid"), &TextureLayeredRD::set_texture_rd_rid);
129 ClassDB::bind_method(D_METHOD("get_texture_rd_rid"), &TextureLayeredRD::get_texture_rd_rid);
130
131 ADD_PROPERTY(PropertyInfo(Variant::RID, "texture_rd_rid"), "set_texture_rd_rid", "get_texture_rd_rid");
132}
133
134TextureLayered::LayeredType TextureLayeredRD::get_layered_type() const {
135 return layer_type;
136}
137
138Image::Format TextureLayeredRD::get_format() const {
139 return image_format;
140}
141
142int TextureLayeredRD::get_width() const {
143 return size.width;
144}
145
146int TextureLayeredRD::get_height() const {
147 return size.height;
148}
149
150int TextureLayeredRD::get_layers() const {
151 return (int)layers;
152}
153
154bool TextureLayeredRD::has_mipmaps() const {
155 return mipmaps > 1;
156}
157
158RID TextureLayeredRD::get_rid() const {
159 if (texture_rid.is_null()) {
160 // We are in trouble, create something temporary.
161 texture_rid = RenderingServer::get_singleton()->texture_2d_placeholder_create();
162 }
163
164 return texture_rid;
165}
166
167Ref<Image> TextureLayeredRD::get_layer_data(int p_layer) const {
168 ERR_FAIL_INDEX_V(p_layer, (int)layers, Ref<Image>());
169 return RS::get_singleton()->texture_2d_layer_get(texture_rid, p_layer);
170}
171
172void TextureLayeredRD::set_texture_rd_rid(RID p_texture_rd_rid) {
173 ERR_FAIL_NULL(RS::get_singleton());
174
175 if (p_texture_rd_rid.is_valid()) {
176 ERR_FAIL_NULL(RD::get_singleton());
177 ERR_FAIL_COND(!RD::get_singleton()->texture_is_valid(p_texture_rd_rid));
178
179 RS::TextureLayeredType rs_layer_type;
180 RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_texture_rd_rid);
181 ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_2D_ARRAY);
182 ERR_FAIL_COND(tf.depth > 1);
183 switch (layer_type) {
184 case LAYERED_TYPE_2D_ARRAY: {
185 ERR_FAIL_COND(tf.array_layers <= 1);
186 rs_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY;
187 } break;
188 case LAYERED_TYPE_CUBEMAP: {
189 ERR_FAIL_COND(tf.array_layers != 6);
190 rs_layer_type = RS::TEXTURE_LAYERED_CUBEMAP;
191 } break;
192 case LAYERED_TYPE_CUBEMAP_ARRAY: {
193 ERR_FAIL_COND((tf.array_layers == 0) || ((tf.array_layers % 6) != 0));
194 rs_layer_type = RS::TEXTURE_LAYERED_CUBEMAP_ARRAY;
195 } break;
196 default: {
197 ERR_FAIL_MSG("Unknown layer type selected");
198 } break;
199 }
200
201 size.width = tf.width;
202 size.height = tf.height;
203 layers = tf.array_layers;
204 mipmaps = tf.mipmaps;
205
206 texture_rd_rid = p_texture_rd_rid;
207
208 if (texture_rid.is_valid()) {
209 RS::get_singleton()->texture_replace(texture_rid, RS::get_singleton()->texture_rd_create(p_texture_rd_rid, rs_layer_type));
210 } else {
211 texture_rid = RS::get_singleton()->texture_rd_create(p_texture_rd_rid, rs_layer_type);
212 }
213
214 image_format = RS::get_singleton()->texture_get_format(texture_rid);
215
216 notify_property_list_changed();
217 emit_changed();
218 } else if (texture_rid.is_valid()) {
219 RS::get_singleton()->free(texture_rid);
220 texture_rid = RID();
221 image_format = Image::FORMAT_MAX;
222 size = Size2i();
223 layers = 0;
224 mipmaps = 0;
225
226 notify_property_list_changed();
227 emit_changed();
228 }
229}
230
231RID TextureLayeredRD::get_texture_rd_rid() const {
232 return texture_rd_rid;
233}
234
235TextureLayeredRD::TextureLayeredRD(LayeredType p_layer_type) {
236 layer_type = p_layer_type;
237 size = Size2i();
238 image_format = Image::FORMAT_MAX;
239 layers = 0;
240 mipmaps = 0;
241}
242
243TextureLayeredRD::~TextureLayeredRD() {
244 if (texture_rid.is_valid()) {
245 ERR_FAIL_NULL(RS::get_singleton());
246 RS::get_singleton()->free(texture_rid);
247 texture_rid = RID();
248 }
249}
250
251////////////////////////////////////////////////////////////////////////////
252// Texture3DRD
253
254void Texture3DRD::_bind_methods() {
255 ClassDB::bind_method(D_METHOD("set_texture_rd_rid", "texture_rd_rid"), &Texture3DRD::set_texture_rd_rid);
256 ClassDB::bind_method(D_METHOD("get_texture_rd_rid"), &Texture3DRD::get_texture_rd_rid);
257
258 ADD_PROPERTY(PropertyInfo(Variant::RID, "texture_rd_rid"), "set_texture_rd_rid", "get_texture_rd_rid");
259}
260
261Image::Format Texture3DRD::get_format() const {
262 return image_format;
263}
264
265int Texture3DRD::get_width() const {
266 return size.x;
267}
268
269int Texture3DRD::get_height() const {
270 return size.y;
271}
272
273int Texture3DRD::get_depth() const {
274 return size.z;
275}
276
277bool Texture3DRD::has_mipmaps() const {
278 return mipmaps > 1;
279}
280
281RID Texture3DRD::get_rid() const {
282 if (texture_rid.is_null()) {
283 // We are in trouble, create something temporary.
284 texture_rid = RenderingServer::get_singleton()->texture_2d_placeholder_create();
285 }
286
287 return texture_rid;
288}
289
290void Texture3DRD::set_texture_rd_rid(RID p_texture_rd_rid) {
291 ERR_FAIL_NULL(RS::get_singleton());
292
293 if (p_texture_rd_rid.is_valid()) {
294 ERR_FAIL_NULL(RD::get_singleton());
295 ERR_FAIL_COND(!RD::get_singleton()->texture_is_valid(p_texture_rd_rid));
296
297 RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_texture_rd_rid);
298 ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_3D);
299 ERR_FAIL_COND(tf.array_layers > 1);
300
301 size.x = tf.width;
302 size.y = tf.height;
303 size.z = tf.depth;
304 mipmaps = tf.mipmaps;
305
306 texture_rd_rid = p_texture_rd_rid;
307
308 if (texture_rid.is_valid()) {
309 RS::get_singleton()->texture_replace(texture_rid, RS::get_singleton()->texture_rd_create(p_texture_rd_rid));
310 } else {
311 texture_rid = RS::get_singleton()->texture_rd_create(p_texture_rd_rid);
312 }
313
314 image_format = RS::get_singleton()->texture_get_format(texture_rid);
315
316 notify_property_list_changed();
317 emit_changed();
318 } else if (texture_rid.is_valid()) {
319 RS::get_singleton()->free(texture_rid);
320 texture_rid = RID();
321 image_format = Image::FORMAT_MAX;
322 size = Vector3i();
323 mipmaps = 0;
324
325 notify_property_list_changed();
326 emit_changed();
327 }
328}
329
330RID Texture3DRD::get_texture_rd_rid() const {
331 return texture_rd_rid;
332}
333
334Texture3DRD::Texture3DRD() {
335 image_format = Image::FORMAT_MAX;
336 size = Vector3i();
337 mipmaps = 0;
338}
339
340Texture3DRD::~Texture3DRD() {
341 if (texture_rid.is_valid()) {
342 ERR_FAIL_NULL(RS::get_singleton());
343 RS::get_singleton()->free(texture_rid);
344 texture_rid = RID();
345 }
346}
347