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_UINT
;
123 case xa_format_z24s8
:
124 fdesc
.format
= PIPE_FORMAT_S8_UINT_Z24_UNORM
;
127 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
130 fdesc
.xa_format
= xa_format_unknown
;
136 XA_EXPORT
struct xa_tracker
*
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 * Don't recreate if we're dropping the scanout flag.
225 if (flag_diff
& XA_FLAG_SCANOUT
)
226 return ((new_flags
& XA_FLAG_SCANOUT
) == 0);
229 * Always recreate for unknown / unimplemented flags.
234 static struct xa_format_descriptor
235 xa_get_format_stype_depth(struct xa_tracker
*xa
,
236 enum xa_surface_type stype
, unsigned int depth
)
239 struct xa_format_descriptor fdesc
;
242 for (i
= xa
->format_map
[stype
][0]; i
<= xa
->format_map
[stype
][1]; ++i
) {
243 fdesc
= xa_get_pipe_format(xa
->supported_formats
[i
]);
244 if (fdesc
.xa_format
!= xa_format_unknown
&&
245 xa_format_depth(fdesc
.xa_format
) == depth
) {
252 fdesc
.xa_format
= xa_format_unknown
;
258 xa_format_check_supported(struct xa_tracker
*xa
,
259 enum xa_formats xa_format
, unsigned int flags
)
261 struct xa_format_descriptor fdesc
= xa_get_pipe_format(xa_format
);
264 if (fdesc
.xa_format
== xa_format_unknown
)
265 return -XA_ERR_INVAL
;
267 bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
268 if (flags
& XA_FLAG_SHARED
)
269 bind
|= PIPE_BIND_SHARED
;
270 if (flags
& XA_FLAG_RENDER_TARGET
)
271 bind
|= PIPE_BIND_RENDER_TARGET
;
272 if (flags
& XA_FLAG_SCANOUT
)
273 bind
|= PIPE_BIND_SCANOUT
;
275 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
276 PIPE_TEXTURE_2D
, 0, bind
))
277 return -XA_ERR_INVAL
;
282 static struct xa_surface
*
283 surface_create(struct xa_tracker
*xa
,
287 enum xa_surface_type stype
,
288 enum xa_formats xa_format
, unsigned int flags
,
289 struct winsys_handle
*whandle
)
291 struct pipe_resource
*template;
292 struct xa_surface
*srf
;
293 struct xa_format_descriptor fdesc
;
295 if (xa_format
== xa_format_unknown
)
296 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
298 fdesc
= xa_get_pipe_format(xa_format
);
300 if (fdesc
.xa_format
== xa_format_unknown
)
303 srf
= calloc(1, sizeof(*srf
));
307 template = &srf
->template;
308 template->format
= fdesc
.format
;
309 template->target
= PIPE_TEXTURE_2D
;
310 template->width0
= width
;
311 template->height0
= height
;
312 template->depth0
= 1;
313 template->array_size
= 1;
314 template->last_level
= 0;
315 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
317 if (flags
& XA_FLAG_SHARED
)
318 template->bind
|= PIPE_BIND_SHARED
;
319 if (flags
& XA_FLAG_RENDER_TARGET
)
320 template->bind
|= PIPE_BIND_RENDER_TARGET
;
321 if (flags
& XA_FLAG_SCANOUT
)
322 template->bind
|= PIPE_BIND_SCANOUT
;
325 srf
->tex
= xa
->screen
->resource_from_handle(xa
->screen
, template, whandle
);
327 srf
->tex
= xa
->screen
->resource_create(xa
->screen
, template);
342 XA_EXPORT
struct xa_surface
*
343 xa_surface_create(struct xa_tracker
*xa
,
347 enum xa_surface_type stype
,
348 enum xa_formats xa_format
, unsigned int flags
)
350 return surface_create(xa
, width
, height
, depth
, stype
, xa_format
, flags
, NULL
);
354 XA_EXPORT
struct xa_surface
*
355 xa_surface_from_handle(struct xa_tracker
*xa
,
359 enum xa_surface_type stype
,
360 enum xa_formats xa_format
, unsigned int flags
,
361 uint32_t handle
, uint32_t stride
)
363 struct winsys_handle whandle
;
364 memset(&whandle
, 0, sizeof(whandle
));
365 whandle
.handle
= handle
;
366 whandle
.stride
= stride
;
367 return surface_create(xa
, width
, height
, depth
, stype
, xa_format
, flags
, &whandle
);
371 xa_surface_redefine(struct xa_surface
*srf
,
375 enum xa_surface_type stype
,
376 enum xa_formats xa_format
,
377 unsigned int new_flags
,
380 struct pipe_resource
*template = &srf
->template;
381 struct pipe_resource
*texture
;
382 struct pipe_box src_box
;
383 struct xa_tracker
*xa
= srf
->xa
;
386 unsigned int save_format
;
387 struct xa_format_descriptor fdesc
;
390 if (xa_format
== xa_format_unknown
)
391 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
393 fdesc
= xa_get_pipe_format(xa_format
);
395 if (width
== template->width0
&& height
== template->height0
&&
396 template->format
== fdesc
.format
&&
397 xa_flags_compat(srf
->flags
, new_flags
))
400 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
401 if (new_flags
& XA_FLAG_SHARED
)
402 template->bind
|= PIPE_BIND_SHARED
;
403 if (new_flags
& XA_FLAG_RENDER_TARGET
)
404 template->bind
|= PIPE_BIND_RENDER_TARGET
;
405 if (new_flags
& XA_FLAG_SCANOUT
)
406 template->bind
|= PIPE_BIND_SCANOUT
;
409 if (!xa_format_type_is_color(fdesc
.xa_format
) ||
410 xa_format_type(fdesc
.xa_format
) == xa_type_a
)
411 return -XA_ERR_INVAL
;
413 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
416 PIPE_BIND_RENDER_TARGET
))
417 return -XA_ERR_INVAL
;
420 save_width
= template->width0
;
421 save_height
= template->height0
;
422 save_format
= template->format
;
424 template->width0
= width
;
425 template->height0
= height
;
426 template->format
= fdesc
.format
;
428 texture
= xa
->screen
->resource_create(xa
->screen
, template);
430 template->width0
= save_width
;
431 template->height0
= save_height
;
432 template->format
= save_format
;
433 return -XA_ERR_NORES
;
437 struct pipe_context
*pipe
= xa
->default_ctx
->pipe
;
439 u_box_origin_2d(xa_min(save_width
, template->width0
),
440 xa_min(save_height
, template->height0
), &src_box
);
441 pipe
->resource_copy_region(pipe
, texture
,
442 0, 0, 0, 0, srf
->tex
, 0, &src_box
);
443 pipe
->flush(pipe
, &xa
->default_ctx
->last_fence
, 0);
446 pipe_resource_reference(&srf
->tex
, texture
);
447 pipe_resource_reference(&texture
, NULL
);
449 srf
->flags
= new_flags
;
455 xa_surface_destroy(struct xa_surface
*srf
)
457 pipe_resource_reference(&srf
->tex
, NULL
);
462 xa_tracker_version(int *major
, int *minor
, int *patch
)
464 *major
= XA_TRACKER_VERSION_MAJOR
;
465 *minor
= XA_TRACKER_VERSION_MINOR
;
466 *patch
= XA_TRACKER_VERSION_PATCH
;
470 xa_surface_handle(struct xa_surface
*srf
,
471 enum xa_handle_type type
,
472 uint32_t * handle
, unsigned int *stride
)
474 struct winsys_handle whandle
;
476 struct pipe_screen
*screen
= srf
->xa
->screen
;
479 memset(&whandle
, 0, sizeof(whandle
));
481 case xa_handle_type_kms
:
482 whandle
.type
= DRM_API_HANDLE_TYPE_KMS
;
484 case xa_handle_type_shared
:
486 whandle
.type
= DRM_API_HANDLE_TYPE_SHARED
;
489 res
= screen
->resource_get_handle(screen
, srf
->tex
, &whandle
);
491 return -XA_ERR_INVAL
;
493 *handle
= whandle
.handle
;
494 *stride
= whandle
.stride
;
499 XA_EXPORT
enum xa_formats
500 xa_surface_format(const struct xa_surface
*srf
)
502 return srf
->fdesc
.xa_format
;