Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | serge | 1 | /* |
2 | * Copyright (C) 2009 Maciej Cencora. |
||
3 | * Copyright (C) 2008 Nicolai Haehnle. |
||
4 | * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
||
5 | * |
||
6 | * The Weather Channel (TM) funded Tungsten Graphics to develop the |
||
7 | * initial release of the Radeon 8500 driver under the XFree86 license. |
||
8 | * This notice must be preserved. |
||
9 | * |
||
10 | * Permission is hereby granted, free of charge, to any person obtaining |
||
11 | * a copy of this software and associated documentation files (the |
||
12 | * "Software"), to deal in the Software without restriction, including |
||
13 | * without limitation the rights to use, copy, modify, merge, publish, |
||
14 | * distribute, sublicense, and/or sell copies of the Software, and to |
||
15 | * permit persons to whom the Software is furnished to do so, subject to |
||
16 | * the following conditions: |
||
17 | * |
||
18 | * The above copyright notice and this permission notice (including the |
||
19 | * next paragraph) shall be included in all copies or substantial |
||
20 | * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
||
26 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||
27 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||
28 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
29 | * |
||
30 | */ |
||
31 | |||
32 | #include "main/glheader.h" |
||
33 | #include "main/imports.h" |
||
34 | #include "main/context.h" |
||
35 | #include "main/enums.h" |
||
36 | #include "main/mipmap.h" |
||
37 | #include "main/pbo.h" |
||
38 | #include "main/texcompress.h" |
||
39 | #include "main/texstore.h" |
||
40 | #include "main/teximage.h" |
||
41 | #include "main/texobj.h" |
||
42 | #include "drivers/common/meta.h" |
||
43 | |||
44 | #include "xmlpool.h" /* for symbolic values of enum-type options */ |
||
45 | |||
46 | #include "radeon_common.h" |
||
47 | |||
48 | #include "radeon_mipmap_tree.h" |
||
49 | |||
50 | static void teximage_assign_miptree(radeonContextPtr rmesa, |
||
51 | struct gl_texture_object *texObj, |
||
52 | struct gl_texture_image *texImage); |
||
53 | |||
54 | static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa, |
||
55 | struct gl_texture_object *texObj, |
||
56 | struct gl_texture_image *texImage); |
||
57 | |||
58 | void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride, |
||
59 | GLuint numrows, GLuint rowsize) |
||
60 | { |
||
61 | assert(rowsize <= dststride); |
||
62 | assert(rowsize <= srcstride); |
||
63 | |||
64 | radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
||
65 | "%s dst %p, stride %u, src %p, stride %u, " |
||
66 | "numrows %u, rowsize %u.\n", |
||
67 | __func__, dst, dststride, |
||
68 | src, srcstride, |
||
69 | numrows, rowsize); |
||
70 | |||
71 | if (rowsize == srcstride && rowsize == dststride) { |
||
72 | memcpy(dst, src, numrows*rowsize); |
||
73 | } else { |
||
74 | GLuint i; |
||
75 | for(i = 0; i < numrows; ++i) { |
||
76 | memcpy(dst, src, rowsize); |
||
77 | dst += dststride; |
||
78 | src += srcstride; |
||
79 | } |
||
80 | } |
||
81 | } |
||
82 | |||
83 | /* textures */ |
||
84 | /** |
||
85 | * Allocate an empty texture image object. |
||
86 | */ |
||
87 | struct gl_texture_image *radeonNewTextureImage(struct gl_context *ctx) |
||
88 | { |
||
89 | return calloc(1, sizeof(radeon_texture_image)); |
||
90 | } |
||
91 | |||
92 | |||
93 | /** |
||
94 | * Delete a texture image object. |
||
95 | */ |
||
96 | static void |
||
97 | radeonDeleteTextureImage(struct gl_context *ctx, struct gl_texture_image *img) |
||
98 | { |
||
99 | /* nothing special (yet) for radeon_texture_image */ |
||
100 | _mesa_delete_texture_image(ctx, img); |
||
101 | } |
||
102 | |||
103 | static GLboolean |
||
104 | radeonAllocTextureImageBuffer(struct gl_context *ctx, |
||
105 | struct gl_texture_image *timage) |
||
106 | { |
||
107 | radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
||
108 | struct gl_texture_object *texobj = timage->TexObject; |
||
109 | |||
110 | ctx->Driver.FreeTextureImageBuffer(ctx, timage); |
||
111 | |||
112 | if (!_swrast_init_texture_image(timage)) |
||
113 | return GL_FALSE; |
||
114 | |||
115 | teximage_assign_miptree(rmesa, texobj, timage); |
||
116 | |||
117 | return GL_TRUE; |
||
118 | } |
||
119 | |||
120 | |||
121 | /** |
||
122 | * Free memory associated with this texture image. |
||
123 | */ |
||
124 | void radeonFreeTextureImageBuffer(struct gl_context *ctx, struct gl_texture_image *timage) |
||
125 | { |
||
126 | radeon_texture_image* image = get_radeon_texture_image(timage); |
||
127 | |||
128 | if (image->mt) { |
||
129 | radeon_miptree_unreference(&image->mt); |
||
130 | } |
||
131 | if (image->bo) { |
||
132 | radeon_bo_unref(image->bo); |
||
133 | image->bo = NULL; |
||
134 | } |
||
135 | |||
136 | _swrast_free_texture_image_buffer(ctx, timage); |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * Map texture memory/buffer into user space. |
||
141 | * Note: the region of interest parameters are ignored here. |
||
142 | * \param mapOut returns start of mapping of region of interest |
||
143 | * \param rowStrideOut returns row stride in bytes |
||
144 | */ |
||
145 | static void |
||
146 | radeon_map_texture_image(struct gl_context *ctx, |
||
147 | struct gl_texture_image *texImage, |
||
148 | GLuint slice, |
||
149 | GLuint x, GLuint y, GLuint w, GLuint h, |
||
150 | GLbitfield mode, |
||
151 | GLubyte **map, |
||
152 | GLint *stride) |
||
153 | { |
||
154 | radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
||
155 | radeon_texture_image *image = get_radeon_texture_image(texImage); |
||
156 | radeon_mipmap_tree *mt = image->mt; |
||
157 | GLuint texel_size = _mesa_get_format_bytes(texImage->TexFormat); |
||
158 | GLuint width = texImage->Width; |
||
159 | GLuint height = texImage->Height; |
||
160 | struct radeon_bo *bo = !image->mt ? image->bo : image->mt->bo; |
||
161 | unsigned int bw, bh; |
||
162 | GLboolean write = (mode & GL_MAP_WRITE_BIT) != 0; |
||
163 | |||
164 | _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); |
||
165 | assert(y % bh == 0); |
||
166 | y /= bh; |
||
167 | texel_size /= bw; |
||
168 | |||
169 | if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) { |
||
170 | radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, |
||
171 | "%s for texture that is " |
||
172 | "queued for GPU processing.\n", |
||
173 | __func__); |
||
174 | radeon_firevertices(rmesa); |
||
175 | } |
||
176 | |||
177 | if (image->bo) { |
||
178 | /* TFP case */ |
||
179 | radeon_bo_map(image->bo, write); |
||
180 | *stride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0, texImage->TexObject->Target); |
||
181 | *map = bo->ptr; |
||
182 | } else if (likely(mt)) { |
||
183 | void *base; |
||
184 | radeon_mipmap_level *lvl = &image->mt->levels[texImage->Level]; |
||
185 | |||
186 | radeon_bo_map(mt->bo, write); |
||
187 | base = mt->bo->ptr + lvl->faces[image->base.Base.Face].offset; |
||
188 | |||
189 | *stride = lvl->rowstride; |
||
190 | *map = base + (slice * height) * *stride; |
||
191 | } else { |
||
192 | /* texture data is in malloc'd memory */ |
||
193 | |||
194 | assert(map); |
||
195 | |||
196 | *stride = _mesa_format_row_stride(texImage->TexFormat, width); |
||
197 | *map = image->base.Buffer + (slice * height) * *stride; |
||
198 | } |
||
199 | |||
200 | *map += y * *stride + x * texel_size; |
||
201 | } |
||
202 | |||
203 | static void |
||
204 | radeon_unmap_texture_image(struct gl_context *ctx, |
||
205 | struct gl_texture_image *texImage, GLuint slice) |
||
206 | { |
||
207 | radeon_texture_image *image = get_radeon_texture_image(texImage); |
||
208 | |||
209 | if (image->bo) |
||
210 | radeon_bo_unmap(image->bo); |
||
211 | else if (image->mt) |
||
212 | radeon_bo_unmap(image->mt->bo); |
||
213 | } |
||
214 | |||
215 | /* try to find a format which will only need a memcopy */ |
||
216 | static gl_format radeonChoose8888TexFormat(radeonContextPtr rmesa, |
||
217 | GLenum srcFormat, |
||
218 | GLenum srcType, GLboolean fbo) |
||
219 | { |
||
220 | #if defined(RADEON_R100) |
||
221 | /* r100 can only do this */ |
||
222 | return _radeon_texformat_argb8888; |
||
223 | #elif defined(RADEON_R200) |
||
224 | const GLuint ui = 1; |
||
225 | const GLubyte littleEndian = *((const GLubyte *)&ui); |
||
226 | |||
227 | if (fbo) |
||
228 | return _radeon_texformat_argb8888; |
||
229 | |||
230 | if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) || |
||
231 | (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) || |
||
232 | (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || |
||
233 | (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) { |
||
234 | return MESA_FORMAT_RGBA8888; |
||
235 | } else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || |
||
236 | (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) || |
||
237 | (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) || |
||
238 | (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) { |
||
239 | return MESA_FORMAT_RGBA8888_REV; |
||
240 | } else |
||
241 | return _radeon_texformat_argb8888; |
||
242 | #endif |
||
243 | } |
||
244 | |||
245 | gl_format radeonChooseTextureFormat_mesa(struct gl_context * ctx, |
||
246 | GLenum target, |
||
247 | GLint internalFormat, |
||
248 | GLenum format, |
||
249 | GLenum type) |
||
250 | { |
||
251 | return radeonChooseTextureFormat(ctx, internalFormat, format, |
||
252 | type, 0); |
||
253 | } |
||
254 | |||
255 | gl_format radeonChooseTextureFormat(struct gl_context * ctx, |
||
256 | GLint internalFormat, |
||
257 | GLenum format, |
||
258 | GLenum type, GLboolean fbo) |
||
259 | { |
||
260 | radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
||
261 | const GLboolean do32bpt = |
||
262 | (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32); |
||
263 | const GLboolean force16bpt = |
||
264 | (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16); |
||
265 | (void)format; |
||
266 | |||
267 | radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
||
268 | "%s InternalFormat=%s(%d) type=%s format=%s\n", |
||
269 | __func__, |
||
270 | _mesa_lookup_enum_by_nr(internalFormat), internalFormat, |
||
271 | _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format)); |
||
272 | radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
||
273 | "%s do32bpt=%d force16bpt=%d\n", |
||
274 | __func__, do32bpt, force16bpt); |
||
275 | |||
276 | switch (internalFormat) { |
||
277 | case 4: |
||
278 | case GL_RGBA: |
||
279 | case GL_COMPRESSED_RGBA: |
||
280 | switch (type) { |
||
281 | case GL_UNSIGNED_INT_10_10_10_2: |
||
282 | case GL_UNSIGNED_INT_2_10_10_10_REV: |
||
283 | return do32bpt ? _radeon_texformat_argb8888 : |
||
284 | _radeon_texformat_argb1555; |
||
285 | case GL_UNSIGNED_SHORT_4_4_4_4: |
||
286 | case GL_UNSIGNED_SHORT_4_4_4_4_REV: |
||
287 | return _radeon_texformat_argb4444; |
||
288 | case GL_UNSIGNED_SHORT_5_5_5_1: |
||
289 | case GL_UNSIGNED_SHORT_1_5_5_5_REV: |
||
290 | return _radeon_texformat_argb1555; |
||
291 | default: |
||
292 | return do32bpt ? radeonChoose8888TexFormat(rmesa, format, type, fbo) : |
||
293 | _radeon_texformat_argb4444; |
||
294 | } |
||
295 | |||
296 | case 3: |
||
297 | case GL_RGB: |
||
298 | case GL_COMPRESSED_RGB: |
||
299 | switch (type) { |
||
300 | case GL_UNSIGNED_SHORT_4_4_4_4: |
||
301 | case GL_UNSIGNED_SHORT_4_4_4_4_REV: |
||
302 | return _radeon_texformat_argb4444; |
||
303 | case GL_UNSIGNED_SHORT_5_5_5_1: |
||
304 | case GL_UNSIGNED_SHORT_1_5_5_5_REV: |
||
305 | return _radeon_texformat_argb1555; |
||
306 | case GL_UNSIGNED_SHORT_5_6_5: |
||
307 | case GL_UNSIGNED_SHORT_5_6_5_REV: |
||
308 | return _radeon_texformat_rgb565; |
||
309 | default: |
||
310 | return do32bpt ? _radeon_texformat_argb8888 : |
||
311 | _radeon_texformat_rgb565; |
||
312 | } |
||
313 | |||
314 | case GL_RGBA8: |
||
315 | case GL_RGB10_A2: |
||
316 | case GL_RGBA12: |
||
317 | case GL_RGBA16: |
||
318 | return !force16bpt ? |
||
319 | radeonChoose8888TexFormat(rmesa, format, type, fbo) : |
||
320 | _radeon_texformat_argb4444; |
||
321 | |||
322 | case GL_RGBA4: |
||
323 | case GL_RGBA2: |
||
324 | return _radeon_texformat_argb4444; |
||
325 | |||
326 | case GL_RGB5_A1: |
||
327 | return _radeon_texformat_argb1555; |
||
328 | |||
329 | case GL_RGB8: |
||
330 | case GL_RGB10: |
||
331 | case GL_RGB12: |
||
332 | case GL_RGB16: |
||
333 | return !force16bpt ? _radeon_texformat_argb8888 : |
||
334 | _radeon_texformat_rgb565; |
||
335 | |||
336 | case GL_RGB5: |
||
337 | case GL_RGB4: |
||
338 | case GL_R3_G3_B2: |
||
339 | return _radeon_texformat_rgb565; |
||
340 | |||
341 | case GL_ALPHA: |
||
342 | case GL_ALPHA4: |
||
343 | case GL_ALPHA8: |
||
344 | case GL_ALPHA12: |
||
345 | case GL_ALPHA16: |
||
346 | case GL_COMPRESSED_ALPHA: |
||
347 | #if defined(RADEON_R200) |
||
348 | /* r200: can't use a8 format since interpreting hw I8 as a8 would result |
||
349 | in wrong rgb values (same as alpha value instead of 0). */ |
||
350 | return _radeon_texformat_al88; |
||
351 | #else |
||
352 | return MESA_FORMAT_A8; |
||
353 | #endif |
||
354 | case 1: |
||
355 | case GL_LUMINANCE: |
||
356 | case GL_LUMINANCE4: |
||
357 | case GL_LUMINANCE8: |
||
358 | case GL_LUMINANCE12: |
||
359 | case GL_LUMINANCE16: |
||
360 | case GL_COMPRESSED_LUMINANCE: |
||
361 | return MESA_FORMAT_L8; |
||
362 | |||
363 | case 2: |
||
364 | case GL_LUMINANCE_ALPHA: |
||
365 | case GL_LUMINANCE4_ALPHA4: |
||
366 | case GL_LUMINANCE6_ALPHA2: |
||
367 | case GL_LUMINANCE8_ALPHA8: |
||
368 | case GL_LUMINANCE12_ALPHA4: |
||
369 | case GL_LUMINANCE12_ALPHA12: |
||
370 | case GL_LUMINANCE16_ALPHA16: |
||
371 | case GL_COMPRESSED_LUMINANCE_ALPHA: |
||
372 | return _radeon_texformat_al88; |
||
373 | |||
374 | case GL_INTENSITY: |
||
375 | case GL_INTENSITY4: |
||
376 | case GL_INTENSITY8: |
||
377 | case GL_INTENSITY12: |
||
378 | case GL_INTENSITY16: |
||
379 | case GL_COMPRESSED_INTENSITY: |
||
380 | return MESA_FORMAT_I8; |
||
381 | |||
382 | case GL_YCBCR_MESA: |
||
383 | if (type == GL_UNSIGNED_SHORT_8_8_APPLE || |
||
384 | type == GL_UNSIGNED_BYTE) |
||
385 | return MESA_FORMAT_YCBCR; |
||
386 | else |
||
387 | return MESA_FORMAT_YCBCR_REV; |
||
388 | |||
389 | case GL_RGB_S3TC: |
||
390 | case GL_RGB4_S3TC: |
||
391 | case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: |
||
392 | return MESA_FORMAT_RGB_DXT1; |
||
393 | |||
394 | case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: |
||
395 | return MESA_FORMAT_RGBA_DXT1; |
||
396 | |||
397 | case GL_RGBA_S3TC: |
||
398 | case GL_RGBA4_S3TC: |
||
399 | case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: |
||
400 | return MESA_FORMAT_RGBA_DXT3; |
||
401 | |||
402 | case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: |
||
403 | return MESA_FORMAT_RGBA_DXT5; |
||
404 | |||
405 | case GL_ALPHA16F_ARB: |
||
406 | return MESA_FORMAT_ALPHA_FLOAT16; |
||
407 | case GL_ALPHA32F_ARB: |
||
408 | return MESA_FORMAT_ALPHA_FLOAT32; |
||
409 | case GL_LUMINANCE16F_ARB: |
||
410 | return MESA_FORMAT_LUMINANCE_FLOAT16; |
||
411 | case GL_LUMINANCE32F_ARB: |
||
412 | return MESA_FORMAT_LUMINANCE_FLOAT32; |
||
413 | case GL_LUMINANCE_ALPHA16F_ARB: |
||
414 | return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16; |
||
415 | case GL_LUMINANCE_ALPHA32F_ARB: |
||
416 | return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32; |
||
417 | case GL_INTENSITY16F_ARB: |
||
418 | return MESA_FORMAT_INTENSITY_FLOAT16; |
||
419 | case GL_INTENSITY32F_ARB: |
||
420 | return MESA_FORMAT_INTENSITY_FLOAT32; |
||
421 | case GL_RGB16F_ARB: |
||
422 | return MESA_FORMAT_RGBA_FLOAT16; |
||
423 | case GL_RGB32F_ARB: |
||
424 | return MESA_FORMAT_RGBA_FLOAT32; |
||
425 | case GL_RGBA16F_ARB: |
||
426 | return MESA_FORMAT_RGBA_FLOAT16; |
||
427 | case GL_RGBA32F_ARB: |
||
428 | return MESA_FORMAT_RGBA_FLOAT32; |
||
429 | |||
430 | case GL_DEPTH_COMPONENT: |
||
431 | case GL_DEPTH_COMPONENT16: |
||
432 | case GL_DEPTH_COMPONENT24: |
||
433 | case GL_DEPTH_COMPONENT32: |
||
434 | case GL_DEPTH_STENCIL_EXT: |
||
435 | case GL_DEPTH24_STENCIL8_EXT: |
||
436 | return MESA_FORMAT_S8_Z24; |
||
437 | |||
438 | /* EXT_texture_sRGB */ |
||
439 | case GL_SRGB: |
||
440 | case GL_SRGB8: |
||
441 | case GL_SRGB_ALPHA: |
||
442 | case GL_SRGB8_ALPHA8: |
||
443 | case GL_COMPRESSED_SRGB: |
||
444 | case GL_COMPRESSED_SRGB_ALPHA: |
||
445 | return MESA_FORMAT_SARGB8; |
||
446 | |||
447 | case GL_SLUMINANCE: |
||
448 | case GL_SLUMINANCE8: |
||
449 | case GL_COMPRESSED_SLUMINANCE: |
||
450 | return MESA_FORMAT_SL8; |
||
451 | |||
452 | case GL_SLUMINANCE_ALPHA: |
||
453 | case GL_SLUMINANCE8_ALPHA8: |
||
454 | case GL_COMPRESSED_SLUMINANCE_ALPHA: |
||
455 | return MESA_FORMAT_SLA8; |
||
456 | |||
457 | case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: |
||
458 | return MESA_FORMAT_SRGB_DXT1; |
||
459 | case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: |
||
460 | return MESA_FORMAT_SRGBA_DXT1; |
||
461 | case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: |
||
462 | return MESA_FORMAT_SRGBA_DXT3; |
||
463 | case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: |
||
464 | return MESA_FORMAT_SRGBA_DXT5; |
||
465 | |||
466 | default: |
||
467 | _mesa_problem(ctx, |
||
468 | "unexpected internalFormat 0x%x in %s", |
||
469 | (int)internalFormat, __func__); |
||
470 | return MESA_FORMAT_NONE; |
||
471 | } |
||
472 | |||
473 | return MESA_FORMAT_NONE; /* never get here */ |
||
474 | } |
||
475 | |||
476 | /** Check if given image is valid within current texture object. |
||
477 | */ |
||
478 | static void teximage_assign_miptree(radeonContextPtr rmesa, |
||
479 | struct gl_texture_object *texObj, |
||
480 | struct gl_texture_image *texImage) |
||
481 | { |
||
482 | radeonTexObj *t = radeon_tex_obj(texObj); |
||
483 | radeon_texture_image* image = get_radeon_texture_image(texImage); |
||
484 | |||
485 | /* Try using current miptree, or create new if there isn't any */ |
||
486 | if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage)) { |
||
487 | radeon_miptree_unreference(&t->mt); |
||
488 | t->mt = radeon_miptree_create_for_teximage(rmesa, |
||
489 | texObj, |
||
490 | texImage); |
||
491 | |||
492 | radeon_print(RADEON_TEXTURE, RADEON_NORMAL, |
||
493 | "%s: texObj %p, texImage %p, " |
||
494 | "texObj miptree doesn't match, allocated new miptree %p\n", |
||
495 | __FUNCTION__, texObj, texImage, t->mt); |
||
496 | } |
||
497 | |||
498 | /* Miptree alocation may have failed, |
||
499 | * when there was no image for baselevel specified */ |
||
500 | if (t->mt) { |
||
501 | radeon_miptree_reference(t->mt, &image->mt); |
||
502 | } else |
||
503 | radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, |
||
504 | "%s Failed to allocate miptree.\n", __func__); |
||
505 | } |
||
506 | |||
507 | unsigned radeonIsFormatRenderable(gl_format mesa_format) |
||
508 | { |
||
509 | if (mesa_format == _radeon_texformat_argb8888 || mesa_format == _radeon_texformat_rgb565 || |
||
510 | mesa_format == _radeon_texformat_argb1555 || mesa_format == _radeon_texformat_argb4444) |
||
511 | return 1; |
||
512 | |||
513 | switch (mesa_format) |
||
514 | { |
||
515 | case MESA_FORMAT_Z16: |
||
516 | case MESA_FORMAT_S8_Z24: |
||
517 | return 1; |
||
518 | default: |
||
519 | return 0; |
||
520 | } |
||
521 | } |
||
522 | |||
523 | void radeon_image_target_texture_2d(struct gl_context *ctx, GLenum target, |
||
524 | struct gl_texture_object *texObj, |
||
525 | struct gl_texture_image *texImage, |
||
526 | GLeglImageOES image_handle) |
||
527 | { |
||
528 | radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
||
529 | radeonTexObj *t = radeon_tex_obj(texObj); |
||
530 | radeon_texture_image *radeonImage = get_radeon_texture_image(texImage); |
||
531 | __DRIscreen *screen; |
||
532 | __DRIimage *image; |
||
533 | |||
534 | screen = radeon->dri.screen; |
||
535 | image = screen->dri2.image->lookupEGLImage(screen, image_handle, |
||
536 | screen->loaderPrivate); |
||
537 | if (image == NULL) |
||
538 | return; |
||
539 | |||
540 | radeonFreeTextureImageBuffer(ctx, texImage); |
||
541 | |||
542 | texImage->Width = image->width; |
||
543 | texImage->Height = image->height; |
||
544 | texImage->Depth = 1; |
||
545 | texImage->_BaseFormat = GL_RGBA; |
||
546 | texImage->TexFormat = image->format; |
||
547 | radeonImage->base.RowStride = image->pitch; |
||
548 | texImage->InternalFormat = image->internal_format; |
||
549 | |||
550 | if(t->mt) |
||
551 | { |
||
552 | radeon_miptree_unreference(&t->mt); |
||
553 | t->mt = NULL; |
||
554 | } |
||
555 | |||
556 | /* NOTE: The following is *very* ugly and will probably break. But |
||
557 | I don't know how to deal with it, without creating a whole new |
||
558 | function like radeon_miptree_from_bo() so I'm going with the |
||
559 | easy but error-prone way. */ |
||
560 | |||
561 | radeon_try_alloc_miptree(radeon, t); |
||
562 | |||
563 | radeon_miptree_reference(t->mt, &radeonImage->mt); |
||
564 | |||
565 | if (t->mt == NULL) |
||
566 | { |
||
567 | radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, |
||
568 | "%s Failed to allocate miptree.\n", __func__); |
||
569 | return; |
||
570 | } |
||
571 | |||
572 | /* Particularly ugly: this is guaranteed to break, if image->bo is |
||
573 | not of the required size for a miptree. */ |
||
574 | radeon_bo_unref(t->mt->bo); |
||
575 | radeon_bo_ref(image->bo); |
||
576 | t->mt->bo = image->bo; |
||
577 | |||
578 | if (!radeon_miptree_matches_image(t->mt, &radeonImage->base.Base)) |
||
579 | fprintf(stderr, "miptree doesn't match image\n"); |
||
580 | } |
||
581 | |||
582 | gl_format _radeon_texformat_rgba8888 = MESA_FORMAT_NONE; |
||
583 | gl_format _radeon_texformat_argb8888 = MESA_FORMAT_NONE; |
||
584 | gl_format _radeon_texformat_rgb565 = MESA_FORMAT_NONE; |
||
585 | gl_format _radeon_texformat_argb4444 = MESA_FORMAT_NONE; |
||
586 | gl_format _radeon_texformat_argb1555 = MESA_FORMAT_NONE; |
||
587 | gl_format _radeon_texformat_al88 = MESA_FORMAT_NONE; |
||
588 | /*@}*/ |
||
589 | |||
590 | |||
591 | static void |
||
592 | radeonInitTextureFormats(void) |
||
593 | { |
||
594 | if (_mesa_little_endian()) { |
||
595 | _radeon_texformat_rgba8888 = MESA_FORMAT_RGBA8888; |
||
596 | _radeon_texformat_argb8888 = MESA_FORMAT_ARGB8888; |
||
597 | _radeon_texformat_rgb565 = MESA_FORMAT_RGB565; |
||
598 | _radeon_texformat_argb4444 = MESA_FORMAT_ARGB4444; |
||
599 | _radeon_texformat_argb1555 = MESA_FORMAT_ARGB1555; |
||
600 | _radeon_texformat_al88 = MESA_FORMAT_AL88; |
||
601 | } |
||
602 | else { |
||
603 | _radeon_texformat_rgba8888 = MESA_FORMAT_RGBA8888_REV; |
||
604 | _radeon_texformat_argb8888 = MESA_FORMAT_ARGB8888_REV; |
||
605 | _radeon_texformat_rgb565 = MESA_FORMAT_RGB565_REV; |
||
606 | _radeon_texformat_argb4444 = MESA_FORMAT_ARGB4444_REV; |
||
607 | _radeon_texformat_argb1555 = MESA_FORMAT_ARGB1555_REV; |
||
608 | _radeon_texformat_al88 = MESA_FORMAT_AL88_REV; |
||
609 | } |
||
610 | } |
||
611 | |||
612 | void |
||
613 | radeon_init_common_texture_funcs(radeonContextPtr radeon, |
||
614 | struct dd_function_table *functions) |
||
615 | { |
||
616 | functions->NewTextureImage = radeonNewTextureImage; |
||
617 | functions->DeleteTextureImage = radeonDeleteTextureImage; |
||
618 | functions->AllocTextureImageBuffer = radeonAllocTextureImageBuffer; |
||
619 | functions->FreeTextureImageBuffer = radeonFreeTextureImageBuffer; |
||
620 | functions->MapTextureImage = radeon_map_texture_image; |
||
621 | functions->UnmapTextureImage = radeon_unmap_texture_image; |
||
622 | |||
623 | functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa; |
||
624 | |||
625 | functions->CopyTexSubImage = radeonCopyTexSubImage; |
||
626 | |||
627 | functions->Bitmap = _mesa_meta_Bitmap; |
||
628 | functions->EGLImageTargetTexture2D = radeon_image_target_texture_2d; |
||
629 | |||
630 | radeonInitTextureFormats(); |
||
631 | } |
||
632 | |||
633 | static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa, |
||
634 | struct gl_texture_object *texObj, |
||
635 | struct gl_texture_image *texImage) |
||
636 | { |
||
637 | radeonTexObj *t = radeon_tex_obj(texObj); |
||
638 | GLuint firstLevel; |
||
639 | GLuint lastLevel; |
||
640 | int width, height, depth; |
||
641 | int i; |
||
642 | |||
643 | width = texImage->Width; |
||
644 | height = texImage->Height; |
||
645 | depth = texImage->Depth; |
||
646 | |||
647 | if (texImage->Level > texObj->BaseLevel && |
||
648 | (width == 1 || |
||
649 | (texObj->Target != GL_TEXTURE_1D && height == 1) || |
||
650 | (texObj->Target == GL_TEXTURE_3D && depth == 1))) { |
||
651 | /* For this combination, we're at some lower mipmap level and |
||
652 | * some important dimension is 1. We can't extrapolate up to a |
||
653 | * likely base level width/height/depth for a full mipmap stack |
||
654 | * from this info, so just allocate this one level. |
||
655 | */ |
||
656 | firstLevel = texImage->Level; |
||
657 | lastLevel = texImage->Level; |
||
658 | } else { |
||
659 | if (texImage->Level < texObj->BaseLevel) |
||
660 | firstLevel = 0; |
||
661 | else |
||
662 | firstLevel = texObj->BaseLevel; |
||
663 | |||
664 | for (i = texImage->Level; i > firstLevel; i--) { |
||
665 | width <<= 1; |
||
666 | if (height != 1) |
||
667 | height <<= 1; |
||
668 | if (depth != 1) |
||
669 | depth <<= 1; |
||
670 | } |
||
671 | if ((texObj->Sampler.MinFilter == GL_NEAREST || |
||
672 | texObj->Sampler.MinFilter == GL_LINEAR) && |
||
673 | texImage->Level == firstLevel) { |
||
674 | lastLevel = firstLevel; |
||
675 | } else { |
||
676 | lastLevel = firstLevel + _mesa_logbase2(MAX2(MAX2(width, height), depth)); |
||
677 | } |
||
678 | } |
||
679 | |||
680 | return radeon_miptree_create(rmesa, texObj->Target, |
||
681 | texImage->TexFormat, firstLevel, lastLevel - firstLevel + 1, |
||
682 | width, height, depth, |
||
683 | t->tile_bits); |
||
684 | }=><=>=><=>=><=>>>=>=> |