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 "state_tracker/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
;
92 case xa_format_a8r8g8b8
:
93 fdesc
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
95 case xa_format_x8r8g8b8
:
96 fdesc
.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
98 case xa_format_r5g6b5
:
99 fdesc
.format
= PIPE_FORMAT_B5G6R5_UNORM
;
101 case xa_format_x1r5g5b5
:
102 fdesc
.format
= PIPE_FORMAT_B5G5R5A1_UNORM
;
105 if (xa
->screen
->is_format_supported(xa
->screen
, PIPE_FORMAT_R8_UNORM
,
107 stype_bind
[xa_type_a
] |
108 PIPE_BIND_RENDER_TARGET
))
109 fdesc
.format
= PIPE_FORMAT_R8_UNORM
;
111 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
114 fdesc
.format
= PIPE_FORMAT_Z24X8_UNORM
;
117 fdesc
.format
= PIPE_FORMAT_Z16_UNORM
;
120 fdesc
.format
= PIPE_FORMAT_Z32_UNORM
;
122 case xa_format_x8z24
:
123 fdesc
.format
= PIPE_FORMAT_Z24X8_UNORM
;
125 case xa_format_z24x8
:
126 fdesc
.format
= PIPE_FORMAT_X8Z24_UNORM
;
128 case xa_format_s8z24
:
129 fdesc
.format
= PIPE_FORMAT_Z24_UNORM_S8_UINT
;
131 case xa_format_z24s8
:
132 fdesc
.format
= PIPE_FORMAT_S8_UINT_Z24_UNORM
;
135 if (xa
->screen
->is_format_supported(xa
->screen
, PIPE_FORMAT_R8_UNORM
,
137 stype_bind
[xa_type_yuv_component
]))
138 fdesc
.format
= PIPE_FORMAT_R8_UNORM
;
140 fdesc
.format
= PIPE_FORMAT_L8_UNORM
;
143 fdesc
.xa_format
= xa_format_unknown
;
149 XA_EXPORT
struct xa_tracker
*
150 xa_tracker_create(int drm_fd
)
152 struct xa_tracker
*xa
= calloc(1, sizeof(struct xa_tracker
));
153 enum xa_surface_type stype
;
154 unsigned int num_formats
;
160 if (drm_fd
< 0 || (fd
= dup(drm_fd
)) < 0)
163 if (pipe_loader_drm_probe_fd(&xa
->dev
, fd
))
164 xa
->screen
= pipe_loader_create_screen(xa
->dev
);
169 xa
->default_ctx
= xa_context_create(xa
);
170 if (!xa
->default_ctx
)
174 for (stype
= 0; stype
< XA_LAST_SURFACE_TYPE
; ++stype
)
175 num_formats
+= num_preferred
[stype
];
178 xa
->supported_formats
= calloc(num_formats
, sizeof(*xa
->supported_formats
));
179 if (!xa
->supported_formats
)
180 goto out_sf_alloc_fail
;
182 xa
->supported_formats
[0] = xa_format_unknown
;
184 memset(xa
->format_map
, 0, sizeof(xa
->format_map
));
186 for (stype
= 0; stype
< XA_LAST_SURFACE_TYPE
; ++stype
) {
187 unsigned int bind
= stype_bind
[stype
];
188 enum xa_formats xa_format
;
191 for (i
= 0; i
< num_preferred
[stype
]; ++i
) {
192 xa_format
= preferred
[stype
][i
];
194 struct xa_format_descriptor fdesc
=
195 xa_get_pipe_format(xa
, xa_format
);
197 if (xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
198 PIPE_TEXTURE_2D
, 0, bind
)) {
199 if (xa
->format_map
[stype
][0] == 0)
200 xa
->format_map
[stype
][0] = num_formats
;
201 xa
->format_map
[stype
][1] = num_formats
;
202 xa
->supported_formats
[num_formats
++] = xa_format
;
209 xa_context_destroy(xa
->default_ctx
);
211 xa
->screen
->destroy(xa
->screen
);
214 pipe_loader_release(&xa
->dev
, 1);
223 xa_tracker_destroy(struct xa_tracker
*xa
)
225 free(xa
->supported_formats
);
226 xa_context_destroy(xa
->default_ctx
);
227 xa
->screen
->destroy(xa
->screen
);
228 pipe_loader_release(&xa
->dev
, 1);
233 xa_flags_compat(unsigned int old_flags
, unsigned int new_flags
)
235 unsigned int flag_diff
= (old_flags
^ new_flags
);
240 if (flag_diff
& XA_FLAG_SHARED
)
243 * Don't recreate if we're dropping the render target flag.
245 if (flag_diff
& XA_FLAG_RENDER_TARGET
)
246 return ((new_flags
& XA_FLAG_RENDER_TARGET
) == 0);
249 * Don't recreate if we're dropping the scanout flag.
251 if (flag_diff
& XA_FLAG_SCANOUT
)
252 return ((new_flags
& XA_FLAG_SCANOUT
) == 0);
255 * Always recreate for unknown / unimplemented flags.
260 static struct xa_format_descriptor
261 xa_get_format_stype_depth(struct xa_tracker
*xa
,
262 enum xa_surface_type stype
, unsigned int depth
)
265 struct xa_format_descriptor fdesc
;
268 for (i
= xa
->format_map
[stype
][0]; i
<= xa
->format_map
[stype
][1]; ++i
) {
269 fdesc
= xa_get_pipe_format(xa
, xa
->supported_formats
[i
]);
270 if (fdesc
.xa_format
!= xa_format_unknown
&&
271 xa_format_depth(fdesc
.xa_format
) == depth
) {
278 fdesc
.xa_format
= xa_format_unknown
;
284 xa_format_check_supported(struct xa_tracker
*xa
,
285 enum xa_formats xa_format
, unsigned int flags
)
287 struct xa_format_descriptor fdesc
= xa_get_pipe_format(xa
, xa_format
);
290 if (fdesc
.xa_format
== xa_format_unknown
)
291 return -XA_ERR_INVAL
;
293 bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
294 if (flags
& XA_FLAG_SHARED
)
295 bind
|= PIPE_BIND_SHARED
;
296 if (flags
& XA_FLAG_RENDER_TARGET
)
297 bind
|= PIPE_BIND_RENDER_TARGET
;
298 if (flags
& XA_FLAG_SCANOUT
)
299 bind
|= PIPE_BIND_SCANOUT
;
301 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
302 PIPE_TEXTURE_2D
, 0, bind
))
303 return -XA_ERR_INVAL
;
309 handle_type(enum xa_handle_type type
)
312 case xa_handle_type_kms
:
313 return DRM_API_HANDLE_TYPE_KMS
;
314 case xa_handle_type_fd
:
315 return DRM_API_HANDLE_TYPE_FD
;
316 case xa_handle_type_shared
:
318 return DRM_API_HANDLE_TYPE_SHARED
;
322 static struct xa_surface
*
323 surface_create(struct xa_tracker
*xa
,
327 enum xa_surface_type stype
,
328 enum xa_formats xa_format
, unsigned int flags
,
329 struct winsys_handle
*whandle
)
331 struct pipe_resource
*template;
332 struct xa_surface
*srf
;
333 struct xa_format_descriptor fdesc
;
335 if (xa_format
== xa_format_unknown
)
336 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
338 fdesc
= xa_get_pipe_format(xa
, xa_format
);
340 if (fdesc
.xa_format
== xa_format_unknown
)
343 srf
= calloc(1, sizeof(*srf
));
347 template = &srf
->template;
348 template->format
= fdesc
.format
;
349 template->target
= PIPE_TEXTURE_2D
;
350 template->width0
= width
;
351 template->height0
= height
;
352 template->depth0
= 1;
353 template->array_size
= 1;
354 template->last_level
= 0;
355 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
357 if (flags
& XA_FLAG_SHARED
)
358 template->bind
|= PIPE_BIND_SHARED
;
359 if (flags
& XA_FLAG_RENDER_TARGET
)
360 template->bind
|= PIPE_BIND_RENDER_TARGET
;
361 if (flags
& XA_FLAG_SCANOUT
)
362 template->bind
|= PIPE_BIND_SCANOUT
;
365 srf
->tex
= xa
->screen
->resource_from_handle(xa
->screen
, template, whandle
,
366 PIPE_HANDLE_USAGE_READ_WRITE
);
368 srf
->tex
= xa
->screen
->resource_create(xa
->screen
, template);
384 XA_EXPORT
struct xa_surface
*
385 xa_surface_create(struct xa_tracker
*xa
,
389 enum xa_surface_type stype
,
390 enum xa_formats xa_format
, unsigned int flags
)
392 return surface_create(xa
, width
, height
, depth
, stype
, xa_format
, flags
, NULL
);
396 XA_EXPORT
struct xa_surface
*
397 xa_surface_from_handle(struct xa_tracker
*xa
,
401 enum xa_surface_type stype
,
402 enum xa_formats xa_format
, unsigned int flags
,
403 uint32_t handle
, uint32_t stride
)
405 return xa_surface_from_handle2(xa
, width
, height
, depth
, stype
, xa_format
,
406 DRM_API_HANDLE_TYPE_SHARED
, flags
, handle
,
410 XA_EXPORT
struct xa_surface
*
411 xa_surface_from_handle2(struct xa_tracker
*xa
,
415 enum xa_surface_type stype
,
416 enum xa_formats xa_format
, unsigned int flags
,
417 enum xa_handle_type type
,
418 uint32_t handle
, uint32_t stride
)
420 struct winsys_handle whandle
;
421 memset(&whandle
, 0, sizeof(whandle
));
422 whandle
.type
= handle_type(type
);
423 whandle
.handle
= handle
;
424 whandle
.stride
= stride
;
425 return surface_create(xa
, width
, height
, depth
, stype
, xa_format
, flags
, &whandle
);
429 xa_surface_redefine(struct xa_surface
*srf
,
433 enum xa_surface_type stype
,
434 enum xa_formats xa_format
,
435 unsigned int new_flags
,
438 struct pipe_resource
*template = &srf
->template;
439 struct pipe_resource
*texture
;
440 struct pipe_box src_box
;
441 struct xa_tracker
*xa
= srf
->xa
;
444 unsigned int save_format
;
445 struct xa_format_descriptor fdesc
;
448 if (xa_format
== xa_format_unknown
)
449 fdesc
= xa_get_format_stype_depth(xa
, stype
, depth
);
451 fdesc
= xa_get_pipe_format(xa
, xa_format
);
453 if (width
== template->width0
&& height
== template->height0
&&
454 template->format
== fdesc
.format
&&
455 xa_flags_compat(srf
->flags
, new_flags
))
458 template->bind
= stype_bind
[xa_format_type(fdesc
.xa_format
)];
459 if (new_flags
& XA_FLAG_SHARED
)
460 template->bind
|= PIPE_BIND_SHARED
;
461 if (new_flags
& XA_FLAG_RENDER_TARGET
)
462 template->bind
|= PIPE_BIND_RENDER_TARGET
;
463 if (new_flags
& XA_FLAG_SCANOUT
)
464 template->bind
|= PIPE_BIND_SCANOUT
;
467 if (!xa_format_type_is_color(fdesc
.xa_format
) ||
468 xa_format_type(fdesc
.xa_format
) == xa_type_a
)
469 return -XA_ERR_INVAL
;
471 if (!xa
->screen
->is_format_supported(xa
->screen
, fdesc
.format
,
474 PIPE_BIND_RENDER_TARGET
))
475 return -XA_ERR_INVAL
;
478 save_width
= template->width0
;
479 save_height
= template->height0
;
480 save_format
= template->format
;
482 template->width0
= width
;
483 template->height0
= height
;
484 template->format
= fdesc
.format
;
486 texture
= xa
->screen
->resource_create(xa
->screen
, template);
488 template->width0
= save_width
;
489 template->height0
= save_height
;
490 template->format
= save_format
;
491 return -XA_ERR_NORES
;
495 struct pipe_context
*pipe
= xa
->default_ctx
->pipe
;
497 u_box_origin_2d(xa_min(save_width
, template->width0
),
498 xa_min(save_height
, template->height0
), &src_box
);
499 pipe
->resource_copy_region(pipe
, texture
,
500 0, 0, 0, 0, srf
->tex
, 0, &src_box
);
501 xa_context_flush(xa
->default_ctx
);
504 pipe_resource_reference(&srf
->tex
, texture
);
505 pipe_resource_reference(&texture
, NULL
);
507 srf
->flags
= new_flags
;
512 XA_EXPORT
struct xa_surface
*
513 xa_surface_ref(struct xa_surface
*srf
)
523 xa_surface_unref(struct xa_surface
*srf
)
525 if (srf
== NULL
|| --srf
->refcount
) {
528 pipe_resource_reference(&srf
->tex
, NULL
);
533 xa_tracker_version(int *major
, int *minor
, int *patch
)
535 *major
= XA_TRACKER_VERSION_MAJOR
;
536 *minor
= XA_TRACKER_VERSION_MINOR
;
537 *patch
= XA_TRACKER_VERSION_PATCH
;
541 xa_surface_handle(struct xa_surface
*srf
,
542 enum xa_handle_type type
,
543 uint32_t * handle
, unsigned int *stride
)
545 struct winsys_handle whandle
;
547 struct pipe_screen
*screen
= srf
->xa
->screen
;
550 memset(&whandle
, 0, sizeof(whandle
));
551 whandle
.type
= handle_type(type
);
552 res
= screen
->resource_get_handle(screen
, srf
->xa
->default_ctx
->pipe
,
554 PIPE_HANDLE_USAGE_READ_WRITE
);
556 return -XA_ERR_INVAL
;
558 *handle
= whandle
.handle
;
559 *stride
= whandle
.stride
;
564 XA_EXPORT
enum xa_formats
565 xa_surface_format(const struct xa_surface
*srf
)
567 return srf
->fdesc
.xa_format
;