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>
30 #include "xa_tracker.h"
32 #include "pipe/p_state.h"
33 #include "pipe/p_format.h"
34 #include "pipe-loader/pipe_loader.h"
35 #include "frontend/drm_driver.h"
36 #include "util/u_inlines.h"
39 * format_map [xa_surface_type][first..last in list].
40 * Needs to be updated when enum xa_formats is updated.
43 static const enum xa_formats preferred_a
[] = { xa_format_a8
};
45 static const enum xa_formats preferred_argb
[] =
46 { xa_format_a8r8g8b8
, xa_format_x8r8g8b8
, xa_format_r5g6b5
,
49 static const enum xa_formats preferred_z
[] =
50 { xa_format_z32
, xa_format_z24
, xa_format_z16
};
51 static const enum xa_formats preferred_sz
[] =
52 { xa_format_x8z24
, xa_format_s8z24
};
53 static const enum xa_formats preferred_zs
[] =
54 { xa_format_z24x8
, xa_format_z24s8
};
55 static const enum xa_formats preferred_yuv
[] = { xa_format_yuv8
};
57 static const enum xa_formats
*preferred
[] =
58 { NULL
, preferred_a
, preferred_argb
, NULL
, NULL
,
59 preferred_z
, preferred_zs
, preferred_sz
, preferred_yuv
62 static const unsigned int num_preferred
[] = { 0,
63 sizeof(preferred_a
) / sizeof(enum xa_formats
),
64 sizeof(preferred_argb
) / sizeof(enum xa_formats
),
67 sizeof(preferred_z
) / sizeof(enum xa_formats
),
68 sizeof(preferred_zs
) / sizeof(enum xa_formats
),
69 sizeof(preferred_sz
) / sizeof(enum xa_formats
),
70 sizeof(preferred_yuv
) / sizeof(enum xa_formats
)
73 static const unsigned int stype_bind
[XA_LAST_SURFACE_TYPE
] = { 0,
74 PIPE_BIND_SAMPLER_VIEW
,
75 PIPE_BIND_SAMPLER_VIEW
,
76 PIPE_BIND_SAMPLER_VIEW
,
77 PIPE_BIND_SAMPLER_VIEW
,
78 PIPE_BIND_DEPTH_STENCIL
,
79 PIPE_BIND_DEPTH_STENCIL
,
80 PIPE_BIND_DEPTH_STENCIL
,
81 PIPE_BIND_SAMPLER_VIEW
84 static struct xa_format_descriptor
85 xa_get_pipe_format(struct xa_tracker
*xa
, enum xa_formats xa_format
)
87 struct xa_format_descriptor fdesc
;
89 fdesc
.xa_format
= xa_format
;
93 if (xa
->screen
->is_format_supported(xa
->screen
, PIPE_FORMAT_R8_UNORM
,
94 PIPE_TEXTURE_2D
, 0, 0,
95 stype_bind
[xa_type_a
] |
96 PIPE_BIND_RENDER_TARGET
))
97 fdesc
.format
= PIPE_FORMAT_R8_UNORM
;
99 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
101 case xa_format_a8r8g8b8
:
102 fdesc
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
104 case xa_format_x8r8g8b8
:
105 fdesc
.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
107 case xa_format_r5g6b5
:
108 fdesc
.format
= PIPE_FORMAT_B5G6R5_UNORM
;
110 case xa_format_x1r5g5b5
:
111 fdesc
.format
= PIPE_FORMAT_B5G5R5A1_UNORM
;
113 case xa_format_a4r4g4b4
:
114 fdesc
.format
= PIPE_FORMAT_B4G4R4A4_UNORM
;
116 case xa_format_a2b10g10r10
:
117 fdesc
.format
= PIPE_FORMAT_R10G10B10A2_UNORM
;
119 case xa_format_x2b10g10r10
:
120 fdesc
.format
= PIPE_FORMAT_R10G10B10X2_UNORM
;
122 case xa_format_b8g8r8a8
:
123 fdesc
.format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
125 case xa_format_b8g8r8x8
:
126 fdesc
.format
= PIPE_FORMAT_X8R8G8B8_UNORM
;
129 fdesc
.format
= PIPE_FORMAT_Z24X8_UNORM
;
132 fdesc
.format
= PIPE_FORMAT_Z16_UNORM
;
135 fdesc
.format
= PIPE_FORMAT_Z32_UNORM
;
137 case xa_format_x8z24
:
138 fdesc
.format
= PIPE_FORMAT_Z24X8_UNORM
;
140 case xa_format_z24x8
:
141 fdesc
.format
= PIPE_FORMAT_X8Z24_UNORM
;
143 case xa_format_s8z24
:
144 fdesc
.format
= PIPE_FORMAT_Z24_UNORM_S8_UINT
;
146 case xa_format_z24s8
:
147 fdesc
.format
= PIPE_FORMAT_S8_UINT_Z24_UNORM
;
150 if (xa
->screen
->is_format_supported(xa
->screen
, PIPE_FORMAT_R8_UNORM
,
151 PIPE_TEXTURE_2D
, 0, 0,
152 stype_bind
[xa_type_yuv_component
]))
153 fdesc
.format
= PIPE_FORMAT_R8_UNORM
;
155 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
158 fdesc
.xa_format
= xa_format_unknown
;
164 XA_EXPORT
struct xa_tracker
*
165 xa_tracker_create(int drm_fd
)
167 struct xa_tracker
*xa
= calloc(1, sizeof(struct xa_tracker
));
168 enum xa_surface_type stype
;
169 unsigned int num_formats
;
174 if (pipe_loader_drm_probe_fd(&xa
->dev
, drm_fd
))
175 xa
->screen
= pipe_loader_create_screen(xa
->dev
);
180 xa
->default_ctx
= xa_context_create(xa
);
181 if (!xa
->default_ctx
)
185 for (stype
= 0; stype
< XA_LAST_SURFACE_TYPE
; ++stype
)
186 num_formats
+= num_preferred
[stype
];
189 xa
->supported_formats
= calloc(num_formats
, sizeof(*xa
->supported_formats
));
190 if (!xa
->supported_formats
)
191 goto out_sf_alloc_fail
;
193 xa
->supported_formats
[0] = xa_format_unknown
;
195 memset(xa
->format_map
, 0, sizeof(xa
->format_map
));
197 for (stype
= 0; stype
< XA_LAST_SURFACE_TYPE
; ++stype
) {
198 unsigned int bind
= stype_bind
[stype
];
199 enum xa_formats xa_format
;
202 for (i
= 0; i
< num_preferred
[stype
]; ++i
) {
203 xa_format
= preferred
[stype
][i
];
205 struct xa_format_descriptor fdesc
=
206 xa_get_pipe_format(xa
, xa_format
);
208 if (xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
209 PIPE_TEXTURE_2D
, 0, 0, bind
)) {
210 if (xa
->format_map
[stype
][0] == 0)
211 xa
->format_map
[stype
][0] = num_formats
;
212 xa
->format_map
[stype
][1] = num_formats
;
213 xa
->supported_formats
[num_formats
++] = xa_format
;
220 xa_context_destroy(xa
->default_ctx
);
222 xa
->screen
->destroy(xa
->screen
);
225 pipe_loader_release(&xa
->dev
, 1);
232 xa_tracker_destroy(struct xa_tracker
*xa
)
234 free(xa
->supported_formats
);
235 xa_context_destroy(xa
->default_ctx
);
236 xa
->screen
->destroy(xa
->screen
);
237 pipe_loader_release(&xa
->dev
, 1);
238 /* CHECK: The XA API user preserves ownership of the original fd */
243 xa_flags_compat(unsigned int old_flags
, unsigned int new_flags
)
245 unsigned int flag_diff
= (old_flags
^ new_flags
);
250 if (flag_diff
& XA_FLAG_SHARED
)
253 * Don't recreate if we're dropping the render target flag.
255 if (flag_diff
& XA_FLAG_RENDER_TARGET
)
256 return ((new_flags
& XA_FLAG_RENDER_TARGET
) == 0);
259 * Don't recreate if we're dropping the scanout flag.
261 if (flag_diff
& XA_FLAG_SCANOUT
)
262 return ((new_flags
& XA_FLAG_SCANOUT
) == 0);
265 * Always recreate for unknown / unimplemented flags.
270 static struct xa_format_descriptor
271 xa_get_format_stype_depth(struct xa_tracker
*xa
,
272 enum xa_surface_type stype
, unsigned int depth
)
275 struct xa_format_descriptor fdesc
;
278 for (i
= xa
->format_map
[stype
][0]; i
<= xa
->format_map
[stype
][1]; ++i
) {
279 fdesc
= xa_get_pipe_format(xa
, xa
->supported_formats
[i
]);
280 if (fdesc
.xa_format
!= xa_format_unknown
&&
281 xa_format_depth(fdesc
.xa_format
) == depth
) {
288 fdesc
.xa_format
= xa_format_unknown
;
294 xa_format_check_supported(struct xa_tracker
*xa
,
295 enum xa_formats xa_format
, unsigned int flags
)
297 struct xa_format_descriptor fdesc
= xa_get_pipe_format(xa
, xa_format
);
300 if (fdesc
.xa_format
== xa_format_unknown
)
301 return -XA_ERR_INVAL
;
303 bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
304 if (flags
& XA_FLAG_SHARED
)
305 bind
|= PIPE_BIND_SHARED
;
306 if (flags
& XA_FLAG_RENDER_TARGET
)
307 bind
|= PIPE_BIND_RENDER_TARGET
;
308 if (flags
& XA_FLAG_SCANOUT
)
309 bind
|= PIPE_BIND_SCANOUT
;
311 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
312 PIPE_TEXTURE_2D
, 0, 0, bind
))
313 return -XA_ERR_INVAL
;
319 handle_type(enum xa_handle_type type
)
322 case xa_handle_type_kms
:
323 return WINSYS_HANDLE_TYPE_KMS
;
324 case xa_handle_type_fd
:
325 return WINSYS_HANDLE_TYPE_FD
;
326 case xa_handle_type_shared
:
328 return WINSYS_HANDLE_TYPE_SHARED
;
332 static struct xa_surface
*
333 surface_create(struct xa_tracker
*xa
,
337 enum xa_surface_type stype
,
338 enum xa_formats xa_format
, unsigned int flags
,
339 struct winsys_handle
*whandle
)
341 struct pipe_resource
*template;
342 struct xa_surface
*srf
;
343 struct xa_format_descriptor fdesc
;
345 if (xa_format
== xa_format_unknown
)
346 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
348 fdesc
= xa_get_pipe_format(xa
, xa_format
);
350 if (fdesc
.xa_format
== xa_format_unknown
)
353 srf
= calloc(1, sizeof(*srf
));
357 template = &srf
->template;
358 template->format
= fdesc
.format
;
359 template->target
= PIPE_TEXTURE_2D
;
360 template->width0
= width
;
361 template->height0
= height
;
362 template->depth0
= 1;
363 template->array_size
= 1;
364 template->last_level
= 0;
365 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
367 if (flags
& XA_FLAG_SHARED
)
368 template->bind
|= PIPE_BIND_SHARED
;
369 if (flags
& XA_FLAG_RENDER_TARGET
)
370 template->bind
|= PIPE_BIND_RENDER_TARGET
;
371 if (flags
& XA_FLAG_SCANOUT
)
372 template->bind
|= PIPE_BIND_SCANOUT
;
375 srf
->tex
= xa
->screen
->resource_from_handle(xa
->screen
, template, whandle
,
376 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE
);
378 srf
->tex
= xa
->screen
->resource_create(xa
->screen
, template);
394 XA_EXPORT
struct xa_surface
*
395 xa_surface_create(struct xa_tracker
*xa
,
399 enum xa_surface_type stype
,
400 enum xa_formats xa_format
, unsigned int flags
)
402 return surface_create(xa
, width
, height
, depth
, stype
, xa_format
, flags
, NULL
);
406 XA_EXPORT
struct xa_surface
*
407 xa_surface_from_handle(struct xa_tracker
*xa
,
411 enum xa_surface_type stype
,
412 enum xa_formats xa_format
, unsigned int flags
,
413 uint32_t handle
, uint32_t stride
)
415 return xa_surface_from_handle2(xa
, width
, height
, depth
, stype
, xa_format
,
416 WINSYS_HANDLE_TYPE_SHARED
, flags
, handle
,
420 XA_EXPORT
struct xa_surface
*
421 xa_surface_from_handle2(struct xa_tracker
*xa
,
425 enum xa_surface_type stype
,
426 enum xa_formats xa_format
, unsigned int flags
,
427 enum xa_handle_type type
,
428 uint32_t handle
, uint32_t stride
)
430 struct winsys_handle whandle
;
431 memset(&whandle
, 0, sizeof(whandle
));
432 whandle
.type
= handle_type(type
);
433 whandle
.handle
= handle
;
434 whandle
.stride
= stride
;
435 return surface_create(xa
, width
, height
, depth
, stype
, xa_format
, flags
, &whandle
);
439 xa_surface_redefine(struct xa_surface
*srf
,
443 enum xa_surface_type stype
,
444 enum xa_formats xa_format
,
445 unsigned int new_flags
,
448 struct pipe_resource
*template = &srf
->template;
449 struct pipe_resource
*texture
;
450 struct pipe_box src_box
;
451 struct xa_tracker
*xa
= srf
->xa
;
454 unsigned int save_format
;
455 struct xa_format_descriptor fdesc
;
458 if (xa_format
== xa_format_unknown
)
459 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
461 fdesc
= xa_get_pipe_format(xa
, xa_format
);
463 if (width
== template->width0
&& height
== template->height0
&&
464 template->format
== fdesc
.format
&&
465 xa_flags_compat(srf
->flags
, new_flags
))
468 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
469 if (new_flags
& XA_FLAG_SHARED
)
470 template->bind
|= PIPE_BIND_SHARED
;
471 if (new_flags
& XA_FLAG_RENDER_TARGET
)
472 template->bind
|= PIPE_BIND_RENDER_TARGET
;
473 if (new_flags
& XA_FLAG_SCANOUT
)
474 template->bind
|= PIPE_BIND_SCANOUT
;
477 if (!xa_format_type_is_color(fdesc
.xa_format
) ||
478 xa_format_type(fdesc
.xa_format
) == xa_type_a
)
479 return -XA_ERR_INVAL
;
481 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
482 PIPE_TEXTURE_2D
, 0, 0,
484 PIPE_BIND_RENDER_TARGET
))
485 return -XA_ERR_INVAL
;
488 save_width
= template->width0
;
489 save_height
= template->height0
;
490 save_format
= template->format
;
492 template->width0
= width
;
493 template->height0
= height
;
494 template->format
= fdesc
.format
;
496 texture
= xa
->screen
->resource_create(xa
->screen
, template);
498 template->width0
= save_width
;
499 template->height0
= save_height
;
500 template->format
= save_format
;
501 return -XA_ERR_NORES
;
505 struct pipe_context
*pipe
= xa
->default_ctx
->pipe
;
507 u_box_origin_2d(xa_min(save_width
, template->width0
),
508 xa_min(save_height
, template->height0
), &src_box
);
509 pipe
->resource_copy_region(pipe
, texture
,
510 0, 0, 0, 0, srf
->tex
, 0, &src_box
);
511 xa_context_flush(xa
->default_ctx
);
514 pipe_resource_reference(&srf
->tex
, texture
);
515 pipe_resource_reference(&texture
, NULL
);
517 srf
->flags
= new_flags
;
522 XA_EXPORT
struct xa_surface
*
523 xa_surface_ref(struct xa_surface
*srf
)
533 xa_surface_unref(struct xa_surface
*srf
)
535 if (srf
== NULL
|| --srf
->refcount
) {
538 pipe_resource_reference(&srf
->tex
, NULL
);
543 xa_tracker_version(int *major
, int *minor
, int *patch
)
545 *major
= XA_TRACKER_VERSION_MAJOR
;
546 *minor
= XA_TRACKER_VERSION_MINOR
;
547 *patch
= XA_TRACKER_VERSION_PATCH
;
551 xa_surface_handle(struct xa_surface
*srf
,
552 enum xa_handle_type type
,
553 uint32_t * handle
, unsigned int *stride
)
555 struct winsys_handle whandle
;
557 struct pipe_screen
*screen
= srf
->xa
->screen
;
560 memset(&whandle
, 0, sizeof(whandle
));
561 whandle
.type
= handle_type(type
);
562 res
= screen
->resource_get_handle(screen
, srf
->xa
->default_ctx
->pipe
,
564 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE
);
566 return -XA_ERR_INVAL
;
568 *handle
= whandle
.handle
;
569 *stride
= whandle
.stride
;
574 XA_EXPORT
enum xa_formats
575 xa_surface_format(const struct xa_surface
*srf
)
577 return srf
->fdesc
.xa_format
;