1 /**********************************************************
2 * Copyright 2009-2011 VMware, Inc. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 *********************************************************
26 * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
29 #include "xa_tracker.h"
31 #include "pipe/p_state.h"
32 #include "pipe/p_format.h"
33 #include "state_tracker/drm_driver.h"
34 #include "util/u_inlines.h"
37 * format_map [xa_surface_type][first..last in list].
38 * Needs to be updated when enum xa_formats is updated.
41 static const enum xa_formats preferred_a
[] = { xa_format_a8
};
43 static const enum xa_formats preferred_argb
[] =
44 { xa_format_a8r8g8b8
, xa_format_x8r8g8b8
, xa_format_r5g6b5
,
47 static const enum xa_formats preferred_z
[] =
48 { xa_format_z32
, xa_format_z24
, xa_format_z16
};
49 static const enum xa_formats preferred_sz
[] =
50 { xa_format_x8z24
, xa_format_s8z24
};
51 static const enum xa_formats preferred_zs
[] =
52 { xa_format_z24x8
, xa_format_z24s8
};
53 static const enum xa_formats preferred_yuv
[] = { xa_format_yuv8
};
55 static const enum xa_formats
*preferred
[] =
56 { NULL
, preferred_a
, preferred_argb
, NULL
, NULL
,
57 preferred_z
, preferred_zs
, preferred_sz
, preferred_yuv
60 static const unsigned int num_preferred
[] = { 0,
61 sizeof(preferred_a
) / sizeof(enum xa_formats
),
62 sizeof(preferred_argb
) / sizeof(enum xa_formats
),
65 sizeof(preferred_z
) / sizeof(enum xa_formats
),
66 sizeof(preferred_zs
) / sizeof(enum xa_formats
),
67 sizeof(preferred_sz
) / sizeof(enum xa_formats
),
68 sizeof(preferred_yuv
) / sizeof(enum xa_formats
)
71 static const unsigned int stype_bind
[XA_LAST_SURFACE_TYPE
] = { 0,
72 PIPE_BIND_SAMPLER_VIEW
,
73 PIPE_BIND_SAMPLER_VIEW
,
74 PIPE_BIND_SAMPLER_VIEW
,
75 PIPE_BIND_SAMPLER_VIEW
,
76 PIPE_BIND_DEPTH_STENCIL
,
77 PIPE_BIND_DEPTH_STENCIL
,
78 PIPE_BIND_DEPTH_STENCIL
,
79 PIPE_BIND_SAMPLER_VIEW
82 static struct xa_format_descriptor
83 xa_get_pipe_format(enum xa_formats xa_format
)
85 struct xa_format_descriptor fdesc
;
87 fdesc
.xa_format
= xa_format
;
90 case xa_format_a8r8g8b8
:
91 fdesc
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
93 case xa_format_x8r8g8b8
:
94 fdesc
.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
96 case xa_format_r5g6b5
:
97 fdesc
.format
= PIPE_FORMAT_B5G6R5_UNORM
;
99 case xa_format_x1r5g5b5
:
100 fdesc
.format
= PIPE_FORMAT_B5G5R5A1_UNORM
;
103 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
106 fdesc
.format
= PIPE_FORMAT_Z24X8_UNORM
;
109 fdesc
.format
= PIPE_FORMAT_Z16_UNORM
;
112 fdesc
.format
= PIPE_FORMAT_Z32_UNORM
;
114 case xa_format_x8z24
:
115 fdesc
.format
= PIPE_FORMAT_Z24X8_UNORM
;
117 case xa_format_z24x8
:
118 fdesc
.format
= PIPE_FORMAT_X8Z24_UNORM
;
120 case xa_format_s8z24
:
121 fdesc
.format
= PIPE_FORMAT_Z24_UNORM_S8_USCALED
;
123 case xa_format_z24s8
:
124 fdesc
.format
= PIPE_FORMAT_S8_USCALED_Z24_UNORM
;
127 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
130 fdesc
.xa_format
= xa_format_unknown
;
137 xa_tracker_create(int drm_fd
)
139 struct xa_tracker
*xa
= calloc(1, sizeof(struct xa_tracker
));
140 enum xa_surface_type stype
;
141 unsigned int num_formats
;
146 xa
->screen
= driver_descriptor
.create_screen(drm_fd
);
150 xa
->default_ctx
= xa_context_create(xa
);
151 if (!xa
->default_ctx
)
155 for (stype
= 0; stype
< XA_LAST_SURFACE_TYPE
; ++stype
)
156 num_formats
+= num_preferred
[stype
];
159 xa
->supported_formats
= calloc(num_formats
, sizeof(*xa
->supported_formats
));
160 if (!xa
->supported_formats
)
161 goto out_sf_alloc_fail
;
163 xa
->supported_formats
[0] = xa_format_unknown
;
165 memset(xa
->format_map
, 0, sizeof(xa
->format_map
));
167 for (stype
= 0; stype
< XA_LAST_SURFACE_TYPE
; ++stype
) {
168 unsigned int bind
= stype_bind
[stype
];
169 enum xa_formats xa_format
;
172 for (i
= 0; i
< num_preferred
[stype
]; ++i
) {
173 xa_format
= preferred
[stype
][i
];
175 struct xa_format_descriptor fdesc
= xa_get_pipe_format(xa_format
);
177 if (xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
178 PIPE_TEXTURE_2D
, 0, bind
)) {
179 if (xa
->format_map
[stype
][0] == 0)
180 xa
->format_map
[stype
][0] = num_formats
;
181 xa
->format_map
[stype
][1] = num_formats
;
182 xa
->supported_formats
[num_formats
++] = xa_format
;
189 xa_context_destroy(xa
->default_ctx
);
191 xa
->screen
->destroy(xa
->screen
);
198 xa_tracker_destroy(struct xa_tracker
*xa
)
200 free(xa
->supported_formats
);
201 xa_context_destroy(xa
->default_ctx
);
202 xa
->screen
->destroy(xa
->screen
);
207 xa_flags_compat(unsigned int old_flags
, unsigned int new_flags
)
209 unsigned int flag_diff
= (old_flags
^ new_flags
);
214 if (flag_diff
& XA_FLAG_SHARED
)
217 * Don't recreate if we're dropping the render target flag.
219 if (flag_diff
& XA_FLAG_RENDER_TARGET
)
220 return ((new_flags
& XA_FLAG_RENDER_TARGET
) == 0);
223 * Always recreate for unknown / unimplemented flags.
228 static struct xa_format_descriptor
229 xa_get_format_stype_depth(struct xa_tracker
*xa
,
230 enum xa_surface_type stype
, unsigned int depth
)
233 struct xa_format_descriptor fdesc
;
236 for (i
= xa
->format_map
[stype
][0]; i
<= xa
->format_map
[stype
][1]; ++i
) {
237 fdesc
= xa_get_pipe_format(xa
->supported_formats
[i
]);
238 if (fdesc
.xa_format
!= xa_format_unknown
&&
239 xa_format_depth(fdesc
.xa_format
) == depth
) {
246 fdesc
.xa_format
= xa_format_unknown
;
252 xa_surface_create(struct xa_tracker
*xa
,
256 enum xa_surface_type stype
,
257 enum xa_formats xa_format
, unsigned int flags
)
259 struct pipe_resource
*template;
260 struct xa_surface
*srf
;
261 struct xa_format_descriptor fdesc
;
263 if (xa_format
== xa_format_unknown
)
264 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
266 fdesc
= xa_get_pipe_format(xa_format
);
268 if (fdesc
.xa_format
== xa_format_unknown
)
271 srf
= calloc(1, sizeof(*srf
));
275 template = &srf
->template;
276 template->format
= fdesc
.format
;
277 template->target
= PIPE_TEXTURE_2D
;
278 template->width0
= width
;
279 template->height0
= height
;
280 template->depth0
= 1;
281 template->array_size
= 1;
282 template->last_level
= 0;
283 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
285 if (flags
& XA_FLAG_SHARED
)
286 template->bind
|= PIPE_BIND_SHARED
;
287 if (flags
& XA_FLAG_RENDER_TARGET
)
288 template->bind
|= PIPE_BIND_RENDER_TARGET
;
290 srf
->tex
= xa
->screen
->resource_create(xa
->screen
, template);
306 xa_surface_redefine(struct xa_surface
*srf
,
310 enum xa_surface_type stype
,
311 enum xa_formats xa_format
,
312 unsigned int add_flags
,
313 unsigned int remove_flags
, int copy_contents
)
315 struct pipe_resource
*template = &srf
->template;
316 struct pipe_resource
*texture
;
317 struct pipe_box src_box
;
318 struct xa_tracker
*xa
= srf
->xa
;
321 unsigned int new_flags
= (srf
->flags
| add_flags
) & ~(remove_flags
);
322 struct xa_format_descriptor fdesc
;
324 if (xa_format
== xa_format_unknown
)
325 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
327 fdesc
= xa_get_pipe_format(xa_format
);
329 if (width
== template->width0
&& height
== template->height0
&&
330 template->format
== fdesc
.format
&&
331 xa_flags_compat(srf
->flags
, new_flags
))
334 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
335 if (new_flags
& XA_FLAG_SHARED
)
336 template->bind
|= PIPE_BIND_SHARED
;
337 if (new_flags
& XA_FLAG_RENDER_TARGET
)
338 template->bind
|= PIPE_BIND_RENDER_TARGET
;
341 if (!xa_format_type_is_color(fdesc
.xa_format
) ||
342 xa_format_type(fdesc
.xa_format
) == xa_type_a
)
343 return -XA_ERR_INVAL
;
345 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
348 PIPE_BIND_RENDER_TARGET
))
349 return -XA_ERR_INVAL
;
352 save_width
= template->width0
;
353 save_height
= template->height0
;
355 template->width0
= width
;
356 template->height0
= height
;
358 texture
= xa
->screen
->resource_create(xa
->screen
, template);
360 template->width0
= save_width
;
361 template->height0
= save_height
;
362 return -XA_ERR_NORES
;
365 pipe_surface_reference(&srf
->srf
, NULL
);
368 struct pipe_context
*pipe
= xa
->default_ctx
->pipe
;
370 u_box_origin_2d(xa_min(save_width
, template->width0
),
371 xa_min(save_height
, template->height0
), &src_box
);
372 pipe
->resource_copy_region(pipe
, texture
,
373 0, 0, 0, 0, srf
->tex
, 0, &src_box
);
374 pipe
->flush(pipe
, &xa
->default_ctx
->last_fence
);
377 pipe_resource_reference(&srf
->tex
, texture
);
378 pipe_resource_reference(&texture
, NULL
);
380 srf
->flags
= new_flags
;
386 xa_surface_destroy(struct xa_surface
*srf
)
388 pipe_surface_reference(&srf
->srf
, NULL
);
389 pipe_resource_reference(&srf
->tex
, NULL
);
394 xa_tracker_version(int *major
, int *minor
, int *patch
)
396 *major
= XA_TRACKER_VERSION_MAJOR
;
397 *minor
= XA_TRACKER_VERSION_MINOR
;
398 *patch
= XA_TRACKER_VERSION_PATCH
;
402 xa_surface_handle(struct xa_surface
*srf
,
403 uint32_t * handle
, unsigned int *stride
)
405 struct winsys_handle whandle
;
407 struct pipe_screen
*screen
= srf
->xa
->screen
;
410 memset(&whandle
, 0, sizeof(whandle
));
411 whandle
.type
= DRM_API_HANDLE_TYPE_SHARED
;
412 res
= screen
->resource_get_handle(screen
, srf
->tex
, &whandle
);
414 return -XA_ERR_INVAL
;
416 *handle
= whandle
.handle
;
417 *stride
= whandle
.stride
;
423 xa_surface_format(const struct xa_surface
*srf
)
425 return srf
->fdesc
.format
;