2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include <pipe/p_screen.h>
28 #include <util/u_format.h>
29 #include <util/u_math.h>
30 #include <util/u_inlines.h>
31 #include <util/u_memory.h>
32 #include "r600_screen.h"
33 #include "r600_texture.h"
35 unsigned long r600_texture_get_offset(struct r600_texture
*rtex
, unsigned level
, unsigned zslice
, unsigned face
)
37 unsigned long offset
= rtex
->offset
[level
];
39 switch (rtex
->tex
.target
) {
42 return offset
+ zslice
* rtex
->layer_size
[level
];
43 case PIPE_TEXTURE_CUBE
:
45 return offset
+ face
* rtex
->layer_size
[level
];
47 assert(zslice
== 0 && face
== 0);
52 static void r600_setup_miptree(struct r600_screen
*rscreen
, struct r600_texture
*rtex
)
54 struct pipe_texture
*ptex
= &rtex
->tex
;
55 unsigned long w
, h
, stride
, size
, layer_size
, i
, offset
;
57 for (i
= 0, offset
= 0; i
<= ptex
->last_level
; i
++) {
58 w
= u_minify(ptex
->width0
, i
);
59 h
= u_minify(ptex
->height0
, i
);
60 stride
= align(util_format_get_stride(ptex
->format
, w
), 32);
61 layer_size
= stride
* h
;
62 if (ptex
->target
== PIPE_TEXTURE_CUBE
)
63 size
= layer_size
* 6;
65 size
= layer_size
* u_minify(ptex
->depth0
, i
);
66 rtex
->offset
[i
] = offset
;
67 rtex
->layer_size
[i
] = layer_size
;
68 rtex
->pitch
[i
] = stride
/ util_format_get_blocksize(ptex
->format
);
69 rtex
->stride
[i
] = stride
;
70 offset
+= align(size
, 32);
75 static struct pipe_texture
*r600_texture_create(struct pipe_screen
*screen
, const struct pipe_texture
*template)
77 struct r600_texture
*rtex
= CALLOC_STRUCT(r600_texture
);
78 struct r600_screen
*rscreen
= r600_screen(screen
);
83 rtex
->tex
= *template;
84 pipe_reference_init(&rtex
->tex
.reference
, 1);
85 rtex
->tex
.screen
= screen
;
86 r600_setup_miptree(rscreen
, rtex
);
87 rtex
->buffer
= screen
->buffer_create(screen
, 4096, PIPE_BUFFER_USAGE_PIXEL
, rtex
->size
);
92 return (struct pipe_texture
*)&rtex
->tex
;
95 static void r600_texture_destroy(struct pipe_texture
*ptex
)
97 struct r600_texture
*rtex
= (struct r600_texture
*)ptex
;
99 pipe_buffer_reference(&rtex
->buffer
, NULL
);
103 static struct pipe_surface
*r600_get_tex_surface(struct pipe_screen
*screen
,
104 struct pipe_texture
*texture
,
105 unsigned face
, unsigned level
,
106 unsigned zslice
, unsigned flags
)
108 struct r600_texture
*rtex
= (struct r600_texture
*)texture
;
109 struct pipe_surface
*surface
= CALLOC_STRUCT(pipe_surface
);
110 unsigned long offset
;
114 offset
= r600_texture_get_offset(rtex
, level
, zslice
, face
);
115 pipe_reference_init(&surface
->reference
, 1);
116 pipe_texture_reference(&surface
->texture
, texture
);
117 surface
->format
= texture
->format
;
118 surface
->width
= u_minify(texture
->width0
, level
);
119 surface
->height
= u_minify(texture
->height0
, level
);
120 surface
->offset
= offset
;
121 surface
->usage
= flags
;
122 surface
->zslice
= zslice
;
123 surface
->texture
= texture
;
124 surface
->face
= face
;
125 surface
->level
= level
;
129 static void r600_tex_surface_destroy(struct pipe_surface
*surface
)
131 pipe_texture_reference(&surface
->texture
, NULL
);
135 static struct pipe_texture
*r600_texture_blanket(struct pipe_screen
*screen
,
136 const struct pipe_texture
*base
,
137 const unsigned *stride
,
138 struct pipe_buffer
*buffer
)
140 struct r600_texture
*rtex
;
142 /* Support only 2D textures without mipmaps */
143 if (base
->target
!= PIPE_TEXTURE_2D
|| base
->depth0
!= 1 || base
->last_level
!= 0)
145 rtex
= CALLOC_STRUCT(r600_texture
);
149 pipe_reference_init(&rtex
->tex
.reference
, 1);
150 rtex
->tex
.screen
= screen
;
151 rtex
->stride_override
= *stride
;
152 rtex
->pitch
[0] = *stride
/ util_format_get_blocksize(base
->format
);
153 rtex
->stride
[0] = *stride
;
155 rtex
->size
= align(rtex
->stride
[0] * base
->height0
, 32);
156 pipe_buffer_reference(&rtex
->buffer
, buffer
);
160 static struct pipe_video_surface
*r600_video_surface_create(struct pipe_screen
*screen
,
161 enum pipe_video_chroma_format chroma_format
,
162 unsigned width
, unsigned height
)
167 static void r600_video_surface_destroy(struct pipe_video_surface
*vsfc
)
172 void r600_init_screen_texture_functions(struct pipe_screen
*screen
)
174 screen
->texture_create
= r600_texture_create
;
175 screen
->texture_destroy
= r600_texture_destroy
;
176 screen
->get_tex_surface
= r600_get_tex_surface
;
177 screen
->tex_surface_destroy
= r600_tex_surface_destroy
;
178 screen
->texture_blanket
= r600_texture_blanket
;
179 screen
->video_surface_create
= r600_video_surface_create
;
180 screen
->video_surface_destroy
= r600_video_surface_destroy
;
183 boolean
r600_get_texture_buffer(struct pipe_screen
*screen
,
184 struct pipe_texture
*texture
,
185 struct pipe_buffer
**buffer
,
188 struct r600_texture
*rtex
= (struct r600_texture
*)texture
;
193 pipe_buffer_reference(buffer
, rtex
->buffer
);
195 *stride
= rtex
->stride
[0];