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>
31 #include "xa_tracker.h"
33 #include "pipe/p_state.h"
34 #include "pipe/p_format.h"
35 #include "pipe-loader/pipe_loader.h"
36 #include "state_tracker/drm_driver.h"
37 #include "util/u_inlines.h"
40 * format_map [xa_surface_type][first..last in list].
41 * Needs to be updated when enum xa_formats is updated.
44 static const enum xa_formats preferred_a
[] = { xa_format_a8
};
46 static const enum xa_formats preferred_argb
[] =
47 { xa_format_a8r8g8b8
, xa_format_x8r8g8b8
, xa_format_r5g6b5
,
50 static const enum xa_formats preferred_z
[] =
51 { xa_format_z32
, xa_format_z24
, xa_format_z16
};
52 static const enum xa_formats preferred_sz
[] =
53 { xa_format_x8z24
, xa_format_s8z24
};
54 static const enum xa_formats preferred_zs
[] =
55 { xa_format_z24x8
, xa_format_z24s8
};
56 static const enum xa_formats preferred_yuv
[] = { xa_format_yuv8
};
58 static const enum xa_formats
*preferred
[] =
59 { NULL
, preferred_a
, preferred_argb
, NULL
, NULL
,
60 preferred_z
, preferred_zs
, preferred_sz
, preferred_yuv
63 static const unsigned int num_preferred
[] = { 0,
64 sizeof(preferred_a
) / sizeof(enum xa_formats
),
65 sizeof(preferred_argb
) / sizeof(enum xa_formats
),
68 sizeof(preferred_z
) / sizeof(enum xa_formats
),
69 sizeof(preferred_zs
) / sizeof(enum xa_formats
),
70 sizeof(preferred_sz
) / sizeof(enum xa_formats
),
71 sizeof(preferred_yuv
) / sizeof(enum xa_formats
)
74 static const unsigned int stype_bind
[XA_LAST_SURFACE_TYPE
] = { 0,
75 PIPE_BIND_SAMPLER_VIEW
,
76 PIPE_BIND_SAMPLER_VIEW
,
77 PIPE_BIND_SAMPLER_VIEW
,
78 PIPE_BIND_SAMPLER_VIEW
,
79 PIPE_BIND_DEPTH_STENCIL
,
80 PIPE_BIND_DEPTH_STENCIL
,
81 PIPE_BIND_DEPTH_STENCIL
,
82 PIPE_BIND_SAMPLER_VIEW
85 static struct xa_format_descriptor
86 xa_get_pipe_format(struct xa_tracker
*xa
, enum xa_formats xa_format
)
88 struct xa_format_descriptor fdesc
;
90 fdesc
.xa_format
= xa_format
;
93 case xa_format_a8r8g8b8
:
94 fdesc
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
96 case xa_format_x8r8g8b8
:
97 fdesc
.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
99 case xa_format_r5g6b5
:
100 fdesc
.format
= PIPE_FORMAT_B5G6R5_UNORM
;
102 case xa_format_x1r5g5b5
:
103 fdesc
.format
= PIPE_FORMAT_B5G5R5A1_UNORM
;
106 if (xa
->screen
->is_format_supported(xa
->screen
, PIPE_FORMAT_R8_UNORM
,
108 stype_bind
[xa_type_a
] |
109 PIPE_BIND_RENDER_TARGET
))
110 fdesc
.format
= PIPE_FORMAT_R8_UNORM
;
112 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
115 fdesc
.format
= PIPE_FORMAT_Z24X8_UNORM
;
118 fdesc
.format
= PIPE_FORMAT_Z16_UNORM
;
121 fdesc
.format
= PIPE_FORMAT_Z32_UNORM
;
123 case xa_format_x8z24
:
124 fdesc
.format
= PIPE_FORMAT_Z24X8_UNORM
;
126 case xa_format_z24x8
:
127 fdesc
.format
= PIPE_FORMAT_X8Z24_UNORM
;
129 case xa_format_s8z24
:
130 fdesc
.format
= PIPE_FORMAT_Z24_UNORM_S8_UINT
;
132 case xa_format_z24s8
:
133 fdesc
.format
= PIPE_FORMAT_S8_UINT_Z24_UNORM
;
136 if (xa
->screen
->is_format_supported(xa
->screen
, PIPE_FORMAT_R8_UNORM
,
138 stype_bind
[xa_type_yuv_component
]))
139 fdesc
.format
= PIPE_FORMAT_R8_UNORM
;
141 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
144 fdesc
.xa_format
= xa_format_unknown
;
150 XA_EXPORT
struct xa_tracker
*
151 xa_tracker_create(int drm_fd
)
153 struct xa_tracker
*xa
= calloc(1, sizeof(struct xa_tracker
));
154 enum xa_surface_type stype
;
155 unsigned int num_formats
;
161 if (drm_fd
< 0 || (fd
= fcntl(drm_fd
, F_DUPFD_CLOEXEC
, 3)) < 0)
164 if (pipe_loader_drm_probe_fd(&xa
->dev
, fd
))
165 xa
->screen
= pipe_loader_create_screen(xa
->dev
);
170 xa
->default_ctx
= xa_context_create(xa
);
171 if (!xa
->default_ctx
)
175 for (stype
= 0; stype
< XA_LAST_SURFACE_TYPE
; ++stype
)
176 num_formats
+= num_preferred
[stype
];
179 xa
->supported_formats
= calloc(num_formats
, sizeof(*xa
->supported_formats
));
180 if (!xa
->supported_formats
)
181 goto out_sf_alloc_fail
;
183 xa
->supported_formats
[0] = xa_format_unknown
;
185 memset(xa
->format_map
, 0, sizeof(xa
->format_map
));
187 for (stype
= 0; stype
< XA_LAST_SURFACE_TYPE
; ++stype
) {
188 unsigned int bind
= stype_bind
[stype
];
189 enum xa_formats xa_format
;
192 for (i
= 0; i
< num_preferred
[stype
]; ++i
) {
193 xa_format
= preferred
[stype
][i
];
195 struct xa_format_descriptor fdesc
=
196 xa_get_pipe_format(xa
, xa_format
);
198 if (xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
199 PIPE_TEXTURE_2D
, 0, bind
)) {
200 if (xa
->format_map
[stype
][0] == 0)
201 xa
->format_map
[stype
][0] = num_formats
;
202 xa
->format_map
[stype
][1] = num_formats
;
203 xa
->supported_formats
[num_formats
++] = xa_format
;
210 xa_context_destroy(xa
->default_ctx
);
212 xa
->screen
->destroy(xa
->screen
);
215 pipe_loader_release(&xa
->dev
, 1);
224 xa_tracker_destroy(struct xa_tracker
*xa
)
226 free(xa
->supported_formats
);
227 xa_context_destroy(xa
->default_ctx
);
228 xa
->screen
->destroy(xa
->screen
);
229 pipe_loader_release(&xa
->dev
, 1);
234 xa_flags_compat(unsigned int old_flags
, unsigned int new_flags
)
236 unsigned int flag_diff
= (old_flags
^ new_flags
);
241 if (flag_diff
& XA_FLAG_SHARED
)
244 * Don't recreate if we're dropping the render target flag.
246 if (flag_diff
& XA_FLAG_RENDER_TARGET
)
247 return ((new_flags
& XA_FLAG_RENDER_TARGET
) == 0);
250 * Don't recreate if we're dropping the scanout flag.
252 if (flag_diff
& XA_FLAG_SCANOUT
)
253 return ((new_flags
& XA_FLAG_SCANOUT
) == 0);
256 * Always recreate for unknown / unimplemented flags.
261 static struct xa_format_descriptor
262 xa_get_format_stype_depth(struct xa_tracker
*xa
,
263 enum xa_surface_type stype
, unsigned int depth
)
266 struct xa_format_descriptor fdesc
;
269 for (i
= xa
->format_map
[stype
][0]; i
<= xa
->format_map
[stype
][1]; ++i
) {
270 fdesc
= xa_get_pipe_format(xa
, xa
->supported_formats
[i
]);
271 if (fdesc
.xa_format
!= xa_format_unknown
&&
272 xa_format_depth(fdesc
.xa_format
) == depth
) {
279 fdesc
.xa_format
= xa_format_unknown
;
285 xa_format_check_supported(struct xa_tracker
*xa
,
286 enum xa_formats xa_format
, unsigned int flags
)
288 struct xa_format_descriptor fdesc
= xa_get_pipe_format(xa
, xa_format
);
291 if (fdesc
.xa_format
== xa_format_unknown
)
292 return -XA_ERR_INVAL
;
294 bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
295 if (flags
& XA_FLAG_SHARED
)
296 bind
|= PIPE_BIND_SHARED
;
297 if (flags
& XA_FLAG_RENDER_TARGET
)
298 bind
|= PIPE_BIND_RENDER_TARGET
;
299 if (flags
& XA_FLAG_SCANOUT
)
300 bind
|= PIPE_BIND_SCANOUT
;
302 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
303 PIPE_TEXTURE_2D
, 0, bind
))
304 return -XA_ERR_INVAL
;
310 handle_type(enum xa_handle_type type
)
313 case xa_handle_type_kms
:
314 return DRM_API_HANDLE_TYPE_KMS
;
315 case xa_handle_type_fd
:
316 return DRM_API_HANDLE_TYPE_FD
;
317 case xa_handle_type_shared
:
319 return DRM_API_HANDLE_TYPE_SHARED
;
323 static struct xa_surface
*
324 surface_create(struct xa_tracker
*xa
,
328 enum xa_surface_type stype
,
329 enum xa_formats xa_format
, unsigned int flags
,
330 struct winsys_handle
*whandle
)
332 struct pipe_resource
*template;
333 struct xa_surface
*srf
;
334 struct xa_format_descriptor fdesc
;
336 if (xa_format
== xa_format_unknown
)
337 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
339 fdesc
= xa_get_pipe_format(xa
, xa_format
);
341 if (fdesc
.xa_format
== xa_format_unknown
)
344 srf
= calloc(1, sizeof(*srf
));
348 template = &srf
->template;
349 template->format
= fdesc
.format
;
350 template->target
= PIPE_TEXTURE_2D
;
351 template->width0
= width
;
352 template->height0
= height
;
353 template->depth0
= 1;
354 template->array_size
= 1;
355 template->last_level
= 0;
356 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
358 if (flags
& XA_FLAG_SHARED
)
359 template->bind
|= PIPE_BIND_SHARED
;
360 if (flags
& XA_FLAG_RENDER_TARGET
)
361 template->bind
|= PIPE_BIND_RENDER_TARGET
;
362 if (flags
& XA_FLAG_SCANOUT
)
363 template->bind
|= PIPE_BIND_SCANOUT
;
366 srf
->tex
= xa
->screen
->resource_from_handle(xa
->screen
, template, whandle
,
367 PIPE_HANDLE_USAGE_READ_WRITE
);
369 srf
->tex
= xa
->screen
->resource_create(xa
->screen
, template);
385 XA_EXPORT
struct xa_surface
*
386 xa_surface_create(struct xa_tracker
*xa
,
390 enum xa_surface_type stype
,
391 enum xa_formats xa_format
, unsigned int flags
)
393 return surface_create(xa
, width
, height
, depth
, stype
, xa_format
, flags
, NULL
);
397 XA_EXPORT
struct xa_surface
*
398 xa_surface_from_handle(struct xa_tracker
*xa
,
402 enum xa_surface_type stype
,
403 enum xa_formats xa_format
, unsigned int flags
,
404 uint32_t handle
, uint32_t stride
)
406 return xa_surface_from_handle2(xa
, width
, height
, depth
, stype
, xa_format
,
407 DRM_API_HANDLE_TYPE_SHARED
, flags
, handle
,
411 XA_EXPORT
struct xa_surface
*
412 xa_surface_from_handle2(struct xa_tracker
*xa
,
416 enum xa_surface_type stype
,
417 enum xa_formats xa_format
, unsigned int flags
,
418 enum xa_handle_type type
,
419 uint32_t handle
, uint32_t stride
)
421 struct winsys_handle whandle
;
422 memset(&whandle
, 0, sizeof(whandle
));
423 whandle
.type
= handle_type(type
);
424 whandle
.handle
= handle
;
425 whandle
.stride
= stride
;
426 return surface_create(xa
, width
, height
, depth
, stype
, xa_format
, flags
, &whandle
);
430 xa_surface_redefine(struct xa_surface
*srf
,
434 enum xa_surface_type stype
,
435 enum xa_formats xa_format
,
436 unsigned int new_flags
,
439 struct pipe_resource
*template = &srf
->template;
440 struct pipe_resource
*texture
;
441 struct pipe_box src_box
;
442 struct xa_tracker
*xa
= srf
->xa
;
445 unsigned int save_format
;
446 struct xa_format_descriptor fdesc
;
449 if (xa_format
== xa_format_unknown
)
450 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
452 fdesc
= xa_get_pipe_format(xa
, xa_format
);
454 if (width
== template->width0
&& height
== template->height0
&&
455 template->format
== fdesc
.format
&&
456 xa_flags_compat(srf
->flags
, new_flags
))
459 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
460 if (new_flags
& XA_FLAG_SHARED
)
461 template->bind
|= PIPE_BIND_SHARED
;
462 if (new_flags
& XA_FLAG_RENDER_TARGET
)
463 template->bind
|= PIPE_BIND_RENDER_TARGET
;
464 if (new_flags
& XA_FLAG_SCANOUT
)
465 template->bind
|= PIPE_BIND_SCANOUT
;
468 if (!xa_format_type_is_color(fdesc
.xa_format
) ||
469 xa_format_type(fdesc
.xa_format
) == xa_type_a
)
470 return -XA_ERR_INVAL
;
472 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
475 PIPE_BIND_RENDER_TARGET
))
476 return -XA_ERR_INVAL
;
479 save_width
= template->width0
;
480 save_height
= template->height0
;
481 save_format
= template->format
;
483 template->width0
= width
;
484 template->height0
= height
;
485 template->format
= fdesc
.format
;
487 texture
= xa
->screen
->resource_create(xa
->screen
, template);
489 template->width0
= save_width
;
490 template->height0
= save_height
;
491 template->format
= save_format
;
492 return -XA_ERR_NORES
;
496 struct pipe_context
*pipe
= xa
->default_ctx
->pipe
;
498 u_box_origin_2d(xa_min(save_width
, template->width0
),
499 xa_min(save_height
, template->height0
), &src_box
);
500 pipe
->resource_copy_region(pipe
, texture
,
501 0, 0, 0, 0, srf
->tex
, 0, &src_box
);
502 xa_context_flush(xa
->default_ctx
);
505 pipe_resource_reference(&srf
->tex
, texture
);
506 pipe_resource_reference(&texture
, NULL
);
508 srf
->flags
= new_flags
;
513 XA_EXPORT
struct xa_surface
*
514 xa_surface_ref(struct xa_surface
*srf
)
524 xa_surface_unref(struct xa_surface
*srf
)
526 if (srf
== NULL
|| --srf
->refcount
) {
529 pipe_resource_reference(&srf
->tex
, NULL
);
534 xa_tracker_version(int *major
, int *minor
, int *patch
)
536 *major
= XA_TRACKER_VERSION_MAJOR
;
537 *minor
= XA_TRACKER_VERSION_MINOR
;
538 *patch
= XA_TRACKER_VERSION_PATCH
;
542 xa_surface_handle(struct xa_surface
*srf
,
543 enum xa_handle_type type
,
544 uint32_t * handle
, unsigned int *stride
)
546 struct winsys_handle whandle
;
548 struct pipe_screen
*screen
= srf
->xa
->screen
;
551 memset(&whandle
, 0, sizeof(whandle
));
552 whandle
.type
= handle_type(type
);
553 res
= screen
->resource_get_handle(screen
, srf
->xa
->default_ctx
->pipe
,
555 PIPE_HANDLE_USAGE_READ_WRITE
);
557 return -XA_ERR_INVAL
;
559 *handle
= whandle
.handle
;
560 *stride
= whandle
.stride
;
565 XA_EXPORT
enum xa_formats
566 xa_surface_format(const struct xa_surface
*srf
)
568 return srf
->fdesc
.xa_format
;