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 "state_tracker/drm_driver.h"
33 #include "r600_screen.h"
34 #include "r600_context.h"
35 #include "r600_resource.h"
37 extern struct u_resource_vtbl r600_texture_vtbl
;
39 static unsigned long r600_texture_get_offset(struct r600_resource_texture
*rtex
,
40 unsigned level
, unsigned zslice
,
43 unsigned long offset
= rtex
->offset
[level
];
45 switch (rtex
->resource
.base
.b
.target
) {
48 return offset
+ zslice
* rtex
->layer_size
[level
];
49 case PIPE_TEXTURE_CUBE
:
51 return offset
+ face
* rtex
->layer_size
[level
];
53 assert(zslice
== 0 && face
== 0);
58 static void r600_setup_miptree(struct r600_screen
*rscreen
, struct r600_resource_texture
*rtex
)
60 struct pipe_resource
*ptex
= &rtex
->resource
.base
.b
;
61 unsigned long w
, h
, pitch
, size
, layer_size
, i
, offset
;
63 rtex
->bpt
= util_format_get_blocksize(ptex
->format
);
64 for (i
= 0, offset
= 0; i
<= ptex
->last_level
; i
++) {
65 w
= u_minify(ptex
->width0
, i
);
66 h
= u_minify(ptex
->height0
, i
);
67 pitch
= util_format_get_stride(ptex
->format
, align(w
, 64));
68 layer_size
= pitch
* h
;
69 if (ptex
->target
== PIPE_TEXTURE_CUBE
)
70 size
= layer_size
* 6;
72 size
= layer_size
* u_minify(ptex
->depth0
, i
);
73 rtex
->offset
[i
] = offset
;
74 rtex
->layer_size
[i
] = layer_size
;
75 rtex
->pitch
[i
] = pitch
;
81 struct pipe_resource
*r600_texture_create(struct pipe_screen
*screen
,
82 const struct pipe_resource
*templ
)
84 struct r600_resource_texture
*rtex
;
85 struct r600_resource
*resource
;
86 struct r600_screen
*rscreen
= r600_screen(screen
);
88 rtex
= CALLOC_STRUCT(r600_resource_texture
);
92 resource
= &rtex
->resource
;
93 resource
->base
.b
= *templ
;
94 resource
->base
.vtbl
= &r600_texture_vtbl
;
95 pipe_reference_init(&resource
->base
.b
.reference
, 1);
96 resource
->base
.b
.screen
= screen
;
97 r600_setup_miptree(rscreen
, rtex
);
99 /* FIXME alignment 4096 enought ? too much ? */
100 resource
->domain
= r600_domain_from_usage(resource
->base
.b
.bind
);
101 resource
->bo
= radeon_bo(rscreen
->rw
, 0, rtex
->size
, 4096, NULL
);
102 if (resource
->bo
== NULL
) {
107 return &resource
->base
.b
;
110 static void r600_texture_destroy(struct pipe_screen
*screen
,
111 struct pipe_resource
*ptex
)
113 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)ptex
;
114 struct r600_resource
*resource
= &rtex
->resource
;
115 struct r600_screen
*rscreen
= r600_screen(screen
);
118 radeon_bo_decref(rscreen
->rw
, resource
->bo
);
123 static struct pipe_surface
*r600_get_tex_surface(struct pipe_screen
*screen
,
124 struct pipe_resource
*texture
,
125 unsigned face
, unsigned level
,
126 unsigned zslice
, unsigned flags
)
128 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)texture
;
129 struct pipe_surface
*surface
= CALLOC_STRUCT(pipe_surface
);
130 unsigned long offset
;
134 offset
= r600_texture_get_offset(rtex
, level
, zslice
, face
);
135 pipe_reference_init(&surface
->reference
, 1);
136 pipe_resource_reference(&surface
->texture
, texture
);
137 surface
->format
= texture
->format
;
138 surface
->width
= u_minify(texture
->width0
, level
);
139 surface
->height
= u_minify(texture
->height0
, level
);
140 surface
->offset
= offset
;
141 surface
->usage
= flags
;
142 surface
->zslice
= zslice
;
143 surface
->texture
= texture
;
144 surface
->face
= face
;
145 surface
->level
= level
;
149 static void r600_tex_surface_destroy(struct pipe_surface
*surface
)
151 pipe_resource_reference(&surface
->texture
, NULL
);
155 struct pipe_resource
*r600_texture_from_handle(struct pipe_screen
*screen
,
156 const struct pipe_resource
*templ
,
157 struct winsys_handle
*whandle
)
159 struct radeon
*rw
= (struct radeon
*)screen
->winsys
;
160 struct r600_resource_texture
*rtex
;
161 struct r600_resource
*resource
;
162 struct radeon_bo
*bo
= NULL
;
164 bo
= radeon_bo(rw
, whandle
->handle
, 0, 0, NULL
);
169 /* Support only 2D textures without mipmaps */
170 if (templ
->target
!= PIPE_TEXTURE_2D
|| templ
->depth0
!= 1 || templ
->last_level
!= 0)
173 rtex
= CALLOC_STRUCT(r600_resource_texture
);
177 resource
= &rtex
->resource
;
178 resource
->base
.b
= *templ
;
179 resource
->base
.vtbl
= &r600_texture_vtbl
;
180 pipe_reference_init(&resource
->base
.b
.reference
, 1);
181 resource
->base
.b
.screen
= screen
;
183 rtex
->pitch_override
= whandle
->stride
;
184 rtex
->bpt
= util_format_get_blocksize(templ
->format
);
185 rtex
->pitch
[0] = whandle
->stride
;
187 rtex
->size
= align(rtex
->pitch
[0] * templ
->height0
, 64);
189 return &resource
->base
.b
;
192 static unsigned int r600_texture_is_referenced(struct pipe_context
*context
,
193 struct pipe_resource
*texture
,
194 unsigned face
, unsigned level
)
197 return PIPE_REFERENCED_FOR_READ
| PIPE_REFERENCED_FOR_WRITE
;
200 struct pipe_transfer
* r600_texture_get_transfer(struct pipe_context
*ctx
,
201 struct pipe_resource
*texture
,
202 struct pipe_subresource sr
,
204 const struct pipe_box
*box
)
206 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)texture
;
207 struct r600_transfer
*trans
;
209 trans
= CALLOC_STRUCT(r600_transfer
);
212 pipe_resource_reference(&trans
->transfer
.resource
, texture
);
213 trans
->transfer
.sr
= sr
;
214 trans
->transfer
.usage
= usage
;
215 trans
->transfer
.box
= *box
;
216 trans
->transfer
.stride
= rtex
->pitch
[sr
.level
];
217 trans
->offset
= r600_texture_get_offset(rtex
, sr
.level
, box
->z
, sr
.face
);
218 return &trans
->transfer
;
221 void r600_texture_transfer_destroy(struct pipe_context
*ctx
,
222 struct pipe_transfer
*trans
)
224 pipe_resource_reference(&trans
->resource
, NULL
);
228 void* r600_texture_transfer_map(struct pipe_context
*ctx
,
229 struct pipe_transfer
* transfer
)
231 struct r600_transfer
*rtransfer
= (struct r600_transfer
*)transfer
;
232 struct r600_resource
*resource
;
233 enum pipe_format format
= transfer
->resource
->format
;
234 struct r600_screen
*rscreen
= r600_screen(ctx
->screen
);
237 resource
= (struct r600_resource
*)transfer
->resource
;
238 if (radeon_bo_map(rscreen
->rw
, resource
->bo
)) {
241 map
= resource
->bo
->data
;
243 return map
+ rtransfer
->offset
+
244 transfer
->box
.y
/ util_format_get_blockheight(format
) * transfer
->stride
+
245 transfer
->box
.x
/ util_format_get_blockwidth(format
) * util_format_get_blocksize(format
);
248 void r600_texture_transfer_unmap(struct pipe_context
*ctx
,
249 struct pipe_transfer
* transfer
)
251 struct r600_screen
*rscreen
= r600_screen(ctx
->screen
);
252 struct r600_resource
*resource
;
254 resource
= (struct r600_resource
*)transfer
->resource
;
255 radeon_bo_unmap(rscreen
->rw
, resource
->bo
);
258 struct u_resource_vtbl r600_texture_vtbl
=
260 u_default_resource_get_handle
, /* get_handle */
261 r600_texture_destroy
, /* resource_destroy */
262 r600_texture_is_referenced
, /* is_resource_referenced */
263 r600_texture_get_transfer
, /* get_transfer */
264 r600_texture_transfer_destroy
, /* transfer_destroy */
265 r600_texture_transfer_map
, /* transfer_map */
266 u_default_transfer_flush_region
,/* transfer_flush_region */
267 r600_texture_transfer_unmap
, /* transfer_unmap */
268 u_default_transfer_inline_write
/* transfer_inline_write */
271 void r600_init_screen_texture_functions(struct pipe_screen
*screen
)
273 screen
->get_tex_surface
= r600_get_tex_surface
;
274 screen
->tex_surface_destroy
= r600_tex_surface_destroy
;