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_api.h"
33 #include "r600_screen.h"
34 #include "r600_texture.h"
36 extern struct u_resource_vtbl r600_texture_vtbl
;
38 unsigned long r600_texture_get_offset(struct r600_texture
*rtex
, unsigned level
, unsigned zslice
, unsigned face
)
40 unsigned long offset
= rtex
->offset
[level
];
42 switch (rtex
->b
.b
.target
) {
45 return offset
+ zslice
* rtex
->layer_size
[level
];
46 case PIPE_TEXTURE_CUBE
:
48 return offset
+ face
* rtex
->layer_size
[level
];
50 assert(zslice
== 0 && face
== 0);
55 static void r600_setup_miptree(struct r600_screen
*rscreen
, struct r600_texture
*rtex
)
57 struct pipe_resource
*ptex
= &rtex
->b
.b
;
58 unsigned long w
, h
, stride
, size
, layer_size
, i
, offset
;
60 for (i
= 0, offset
= 0; i
<= ptex
->last_level
; i
++) {
61 w
= u_minify(ptex
->width0
, i
);
62 h
= u_minify(ptex
->height0
, i
);
63 stride
= align(util_format_get_stride(ptex
->format
, w
), 32);
64 layer_size
= stride
* h
;
65 if (ptex
->target
== PIPE_TEXTURE_CUBE
)
66 size
= layer_size
* 6;
68 size
= layer_size
* u_minify(ptex
->depth0
, i
);
69 rtex
->offset
[i
] = offset
;
70 rtex
->layer_size
[i
] = layer_size
;
71 rtex
->pitch
[i
] = stride
/ util_format_get_blocksize(ptex
->format
);
72 rtex
->stride
[i
] = stride
;
73 offset
+= align(size
, 32);
78 struct pipe_resource
*r600_texture_create(struct pipe_screen
*screen
,
79 const struct pipe_resource
*templ
)
81 struct r600_texture
*rtex
= CALLOC_STRUCT(r600_texture
);
82 struct r600_screen
*rscreen
= r600_screen(screen
);
83 struct pipe_resource templ_buf
;
89 rtex
->b
.vtbl
= &r600_texture_vtbl
;
90 pipe_reference_init(&rtex
->b
.b
.reference
, 1);
91 rtex
->b
.b
.screen
= screen
;
92 r600_setup_miptree(rscreen
, rtex
);
94 memset(&templ_buf
, 0, sizeof(struct pipe_resource
));
95 templ_buf
.target
= PIPE_BUFFER
;
96 templ_buf
.format
= PIPE_FORMAT_R8_UNORM
;
97 templ_buf
.usage
= templ
->usage
;
98 templ_buf
.bind
= templ
->bind
;
99 templ_buf
.width0
= rtex
->size
;
100 templ_buf
.height0
= 1;
101 templ_buf
.depth0
= 1;
103 rtex
->buffer
= screen
->resource_create(screen
, &templ_buf
);
111 static void r600_texture_destroy(struct pipe_screen
*screen
,
112 struct pipe_resource
*ptex
)
114 struct r600_texture
*rtex
= (struct r600_texture
*)ptex
;
119 static struct pipe_surface
*r600_get_tex_surface(struct pipe_screen
*screen
,
120 struct pipe_resource
*texture
,
121 unsigned face
, unsigned level
,
122 unsigned zslice
, unsigned flags
)
124 struct r600_texture
*rtex
= (struct r600_texture
*)texture
;
125 struct pipe_surface
*surface
= CALLOC_STRUCT(pipe_surface
);
126 unsigned long offset
;
130 offset
= r600_texture_get_offset(rtex
, level
, zslice
, face
);
131 pipe_reference_init(&surface
->reference
, 1);
132 pipe_resource_reference(&surface
->texture
, texture
);
133 surface
->format
= texture
->format
;
134 surface
->width
= u_minify(texture
->width0
, level
);
135 surface
->height
= u_minify(texture
->height0
, level
);
136 surface
->offset
= offset
;
137 surface
->usage
= flags
;
138 surface
->zslice
= zslice
;
139 surface
->texture
= texture
;
140 surface
->face
= face
;
141 surface
->level
= level
;
145 static void r600_tex_surface_destroy(struct pipe_surface
*surface
)
147 pipe_resource_reference(&surface
->texture
, NULL
);
151 struct pipe_resource
*r600_texture_from_handle(struct pipe_screen
*screen
,
152 const struct pipe_resource
*base
,
153 struct winsys_handle
*whandle
)
155 struct pipe_resource
*buffer
;
156 struct r600_texture
*rtex
;
158 buffer
= r600_buffer_from_handle(screen
, whandle
);
159 if (buffer
== NULL
) {
163 /* Support only 2D textures without mipmaps */
164 if (base
->target
!= PIPE_TEXTURE_2D
|| base
->depth0
!= 1 || base
->last_level
!= 0)
167 rtex
= CALLOC_STRUCT(r600_texture
);
171 /* one ref already taken */
172 rtex
->buffer
= buffer
;
175 rtex
->b
.vtbl
= &r600_texture_vtbl
;
176 pipe_reference_init(&rtex
->b
.b
.reference
, 1);
177 rtex
->b
.b
.screen
= screen
;
178 rtex
->stride_override
= whandle
->stride
;
179 rtex
->pitch
[0] = whandle
->stride
/ util_format_get_blocksize(base
->format
);
180 rtex
->stride
[0] = whandle
->stride
;
182 rtex
->size
= align(rtex
->stride
[0] * base
->height0
, 32);
187 static boolean
r600_texture_get_handle(struct pipe_screen
* screen
,
188 struct pipe_resource
*texture
,
189 struct winsys_handle
*whandle
)
191 struct r600_screen
*rscreen
= r600_screen(screen
);
192 struct r600_texture
* rtex
= (struct r600_texture
*)texture
;
198 whandle
->stride
= rtex
->stride
[0];
200 r600_buffer_get_handle(rscreen
->rw
, rtex
->buffer
, whandle
);
205 static unsigned int r600_texture_is_referenced(struct pipe_context
*context
,
206 struct pipe_resource
*texture
,
207 unsigned face
, unsigned level
)
209 struct r600_texture
*rtex
= (struct r600_texture
*)texture
;
211 return r600_buffer_is_referenced_by_cs(context
, rtex
->buffer
, face
, level
);
214 struct u_resource_vtbl r600_texture_vtbl
=
216 r600_texture_get_handle
, /* get_handle */
217 r600_texture_destroy
, /* resource_destroy */
218 r600_texture_is_referenced
, /* is_resource_referenced */
219 r600_texture_get_transfer
, /* get_transfer */
220 r600_texture_transfer_destroy
, /* transfer_destroy */
221 r600_texture_transfer_map
, /* transfer_map */
222 u_default_transfer_flush_region
,/* transfer_flush_region */
223 r600_texture_transfer_unmap
, /* transfer_unmap */
224 u_default_transfer_inline_write
/* transfer_inline_write */
227 void r600_init_screen_texture_functions(struct pipe_screen
*screen
)
229 screen
->get_tex_surface
= r600_get_tex_surface
;
230 screen
->tex_surface_destroy
= r600_tex_surface_destroy
;