1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2009 Younes Manton.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include <assert.h>
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include <X11/Xlibint.h>
31bf215546Sopenharmony_ci#include <X11/extensions/XvMClib.h>
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "pipe/p_screen.h"
34bf215546Sopenharmony_ci#include "pipe/p_video_codec.h"
35bf215546Sopenharmony_ci#include "pipe/p_state.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "util/u_memory.h"
38bf215546Sopenharmony_ci#include "util/u_math.h"
39bf215546Sopenharmony_ci#include "util/format/u_format.h"
40bf215546Sopenharmony_ci#include "util/u_sampler.h"
41bf215546Sopenharmony_ci#include "util/u_surface.h"
42bf215546Sopenharmony_ci#include "util/u_rect.h"
43bf215546Sopenharmony_ci#include "vl/vl_winsys.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#include "xvmc_private.h"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci#define FOURCC_RGB 0x0000003
48bf215546Sopenharmony_ci#define FOURCC_AI44 0x34344941
49bf215546Sopenharmony_ci#define FOURCC_IA44 0x34344149
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_cistatic enum pipe_format XvIDToPipe(struct pipe_screen *screen,
52bf215546Sopenharmony_ci                                   int xvimage_id)
53bf215546Sopenharmony_ci{
54bf215546Sopenharmony_ci   enum pipe_format ret;
55bf215546Sopenharmony_ci   assert(screen);
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci   switch (xvimage_id) {
58bf215546Sopenharmony_ci   case FOURCC_RGB:
59bf215546Sopenharmony_ci      ret = PIPE_FORMAT_B8G8R8X8_UNORM;
60bf215546Sopenharmony_ci      break;
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   case FOURCC_AI44:
63bf215546Sopenharmony_ci      ret = PIPE_FORMAT_R4A4_UNORM;
64bf215546Sopenharmony_ci      if (!screen->is_format_supported(
65bf215546Sopenharmony_ci                screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW))
66bf215546Sopenharmony_ci         ret = PIPE_FORMAT_B4G4R4A4_UNORM;
67bf215546Sopenharmony_ci      break;
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   case FOURCC_IA44:
70bf215546Sopenharmony_ci      ret = PIPE_FORMAT_A4R4_UNORM;
71bf215546Sopenharmony_ci      if (!screen->is_format_supported(
72bf215546Sopenharmony_ci                screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW))
73bf215546Sopenharmony_ci         ret = PIPE_FORMAT_B4G4R4A4_UNORM;
74bf215546Sopenharmony_ci      break;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   default:
77bf215546Sopenharmony_ci      XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
78bf215546Sopenharmony_ci      return PIPE_FORMAT_NONE;
79bf215546Sopenharmony_ci   }
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   if (!screen->is_format_supported(
82bf215546Sopenharmony_ci             screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
83bf215546Sopenharmony_ci      XVMC_MSG(XVMC_ERR, "[XvMC] Unsupported 2D format %s for Xv image ID 0x%08X.\n", util_format_name(ret), xvimage_id);
84bf215546Sopenharmony_ci      ret = PIPE_FORMAT_NONE;
85bf215546Sopenharmony_ci   }
86bf215546Sopenharmony_ci   return ret;
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci}
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_cistatic unsigned NumPaletteEntries4XvID(int xvimage_id)
91bf215546Sopenharmony_ci{
92bf215546Sopenharmony_ci   switch (xvimage_id) {
93bf215546Sopenharmony_ci      case FOURCC_RGB:
94bf215546Sopenharmony_ci         return 0;
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci      case FOURCC_AI44:
97bf215546Sopenharmony_ci      case FOURCC_IA44:
98bf215546Sopenharmony_ci         return 16;
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci      default:
101bf215546Sopenharmony_ci         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
102bf215546Sopenharmony_ci         return 0;
103bf215546Sopenharmony_ci   }
104bf215546Sopenharmony_ci}
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_cistatic int PipeToComponentOrder(struct pipe_screen *screen,
107bf215546Sopenharmony_ci                                enum pipe_format format,
108bf215546Sopenharmony_ci                                enum pipe_format *palette_format,
109bf215546Sopenharmony_ci                                char *component_order)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci   assert(screen);
112bf215546Sopenharmony_ci   assert(component_order);
113bf215546Sopenharmony_ci   assert(palette_format);
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   switch (format) {
116bf215546Sopenharmony_ci   case PIPE_FORMAT_B8G8R8X8_UNORM:
117bf215546Sopenharmony_ci      return 0;
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   case PIPE_FORMAT_A4R4_UNORM:
120bf215546Sopenharmony_ci   case PIPE_FORMAT_R4A4_UNORM:
121bf215546Sopenharmony_ci   case PIPE_FORMAT_B4G4R4A4_UNORM:
122bf215546Sopenharmony_ci      *palette_format = PIPE_FORMAT_R8G8B8X8_UNORM;
123bf215546Sopenharmony_ci      component_order[0] = 'Y';
124bf215546Sopenharmony_ci      component_order[1] = 'U';
125bf215546Sopenharmony_ci      component_order[2] = 'V';
126bf215546Sopenharmony_ci      component_order[3] = 'A';
127bf215546Sopenharmony_ci      if (!screen->is_format_supported(
128bf215546Sopenharmony_ci                screen, *palette_format, PIPE_TEXTURE_1D, 0, 0,
129bf215546Sopenharmony_ci                PIPE_BIND_SAMPLER_VIEW)) {
130bf215546Sopenharmony_ci         /* One of these formats better be supported... */
131bf215546Sopenharmony_ci         *palette_format = PIPE_FORMAT_B8G8R8X8_UNORM;
132bf215546Sopenharmony_ci         component_order[0] = 'V';
133bf215546Sopenharmony_ci         component_order[2] = 'Y';
134bf215546Sopenharmony_ci      }
135bf215546Sopenharmony_ci      return 4;
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   default:
138bf215546Sopenharmony_ci      XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format);
139bf215546Sopenharmony_ci      component_order[0] = 0;
140bf215546Sopenharmony_ci      component_order[1] = 0;
141bf215546Sopenharmony_ci      component_order[2] = 0;
142bf215546Sopenharmony_ci      component_order[3] = 0;
143bf215546Sopenharmony_ci      return 0;
144bf215546Sopenharmony_ci   }
145bf215546Sopenharmony_ci}
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_cistatic Status Validate(Display *dpy, XvPortID port, int surface_type_id, int xvimage_id)
148bf215546Sopenharmony_ci{
149bf215546Sopenharmony_ci   XvImageFormatValues *subpictures;
150bf215546Sopenharmony_ci   int num_subpics;
151bf215546Sopenharmony_ci   int i;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   subpictures = XvMCListSubpictureTypes(dpy, port, surface_type_id, &num_subpics);
154bf215546Sopenharmony_ci   if (num_subpics < 1) {
155bf215546Sopenharmony_ci      free(subpictures);
156bf215546Sopenharmony_ci      return BadMatch;
157bf215546Sopenharmony_ci   }
158bf215546Sopenharmony_ci   if (!subpictures)
159bf215546Sopenharmony_ci      return BadAlloc;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   for (i = 0; i < num_subpics; ++i) {
162bf215546Sopenharmony_ci      if (subpictures[i].id == xvimage_id) {
163bf215546Sopenharmony_ci         XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested subpicture format.\n" \
164bf215546Sopenharmony_ci                              "[XvMC]   port=%u\n" \
165bf215546Sopenharmony_ci                              "[XvMC]   surface id=0x%08X\n" \
166bf215546Sopenharmony_ci                              "[XvMC]   image id=0x%08X\n" \
167bf215546Sopenharmony_ci                              "[XvMC]   type=%08X\n" \
168bf215546Sopenharmony_ci                              "[XvMC]   byte order=%08X\n" \
169bf215546Sopenharmony_ci                              "[XvMC]   bits per pixel=%u\n" \
170bf215546Sopenharmony_ci                              "[XvMC]   format=%08X\n" \
171bf215546Sopenharmony_ci                              "[XvMC]   num planes=%d\n",
172bf215546Sopenharmony_ci                              port, surface_type_id, xvimage_id, subpictures[i].type, subpictures[i].byte_order,
173bf215546Sopenharmony_ci                              subpictures[i].bits_per_pixel, subpictures[i].format, subpictures[i].num_planes);
174bf215546Sopenharmony_ci         if (subpictures[i].type == XvRGB) {
175bf215546Sopenharmony_ci            XVMC_MSG(XVMC_TRACE, "[XvMC]   depth=%d\n" \
176bf215546Sopenharmony_ci                                 "[XvMC]   red mask=0x%08X\n" \
177bf215546Sopenharmony_ci                                 "[XvMC]   green mask=0x%08X\n" \
178bf215546Sopenharmony_ci                                 "[XvMC]   blue mask=0x%08X\n",
179bf215546Sopenharmony_ci                                 subpictures[i].depth, subpictures[i].red_mask,
180bf215546Sopenharmony_ci                                 subpictures[i].green_mask, subpictures[i].blue_mask);
181bf215546Sopenharmony_ci         }
182bf215546Sopenharmony_ci         else if (subpictures[i].type == XvYUV) {
183bf215546Sopenharmony_ci            XVMC_MSG(XVMC_TRACE, "[XvMC]   y sample bits=0x%08X\n" \
184bf215546Sopenharmony_ci                                 "[XvMC]   u sample bits=0x%08X\n" \
185bf215546Sopenharmony_ci                                 "[XvMC]   v sample bits=0x%08X\n" \
186bf215546Sopenharmony_ci                                 "[XvMC]   horz y period=%u\n" \
187bf215546Sopenharmony_ci                                 "[XvMC]   horz u period=%u\n" \
188bf215546Sopenharmony_ci                                 "[XvMC]   horz v period=%u\n" \
189bf215546Sopenharmony_ci                                 "[XvMC]   vert y period=%u\n" \
190bf215546Sopenharmony_ci                                 "[XvMC]   vert u period=%u\n" \
191bf215546Sopenharmony_ci                                 "[XvMC]   vert v period=%u\n",
192bf215546Sopenharmony_ci                                 subpictures[i].y_sample_bits, subpictures[i].u_sample_bits, subpictures[i].v_sample_bits,
193bf215546Sopenharmony_ci                                 subpictures[i].horz_y_period, subpictures[i].horz_u_period, subpictures[i].horz_v_period,
194bf215546Sopenharmony_ci                                 subpictures[i].vert_y_period, subpictures[i].vert_u_period, subpictures[i].vert_v_period);
195bf215546Sopenharmony_ci         }
196bf215546Sopenharmony_ci         break;
197bf215546Sopenharmony_ci      }
198bf215546Sopenharmony_ci   }
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   free(subpictures);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   return i < num_subpics ? Success : BadMatch;
203bf215546Sopenharmony_ci}
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_cistatic void
206bf215546Sopenharmony_ciupload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst,
207bf215546Sopenharmony_ci               const struct pipe_box *dst_box, const void *src, unsigned src_stride,
208bf215546Sopenharmony_ci               unsigned src_x, unsigned src_y)
209bf215546Sopenharmony_ci{
210bf215546Sopenharmony_ci   struct pipe_transfer *transfer;
211bf215546Sopenharmony_ci   void *map;
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   map = pipe->texture_map(pipe, dst->texture, 0, PIPE_MAP_WRITE,
214bf215546Sopenharmony_ci                            dst_box, &transfer);
215bf215546Sopenharmony_ci   if (!map)
216bf215546Sopenharmony_ci      return;
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0,
219bf215546Sopenharmony_ci                  dst_box->width, dst_box->height,
220bf215546Sopenharmony_ci                  src, src_stride, src_x, src_y);
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   pipe->texture_unmap(pipe, transfer);
223bf215546Sopenharmony_ci}
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_cistatic void
226bf215546Sopenharmony_ciupload_sampler_convert(struct pipe_context *pipe, struct pipe_sampler_view *dst,
227bf215546Sopenharmony_ci                       const struct pipe_box *dst_box, const XvImage *image,
228bf215546Sopenharmony_ci                       unsigned src_x, unsigned src_y)
229bf215546Sopenharmony_ci{
230bf215546Sopenharmony_ci   struct pipe_transfer *transfer;
231bf215546Sopenharmony_ci   int i, j;
232bf215546Sopenharmony_ci   char *map, *src;
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci   map = pipe->texture_map(pipe, dst->texture, 0, PIPE_MAP_WRITE,
235bf215546Sopenharmony_ci                            dst_box, &transfer);
236bf215546Sopenharmony_ci   if (!map)
237bf215546Sopenharmony_ci      return;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   src = image->data;
240bf215546Sopenharmony_ci   src += src_y * image->width + src_x;
241bf215546Sopenharmony_ci   if (image->id == FOURCC_AI44) {
242bf215546Sopenharmony_ci      /* The format matches what we want, we just have to insert dummy
243bf215546Sopenharmony_ci       * bytes. So just copy the same value in twice.
244bf215546Sopenharmony_ci       */
245bf215546Sopenharmony_ci      for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width)
246bf215546Sopenharmony_ci         for (j = 0; j < dst_box->width; j++)
247bf215546Sopenharmony_ci            map[j * 2 + 0] = map[j * 2 + 1] = src[j];
248bf215546Sopenharmony_ci   } else {
249bf215546Sopenharmony_ci      assert(image->id == FOURCC_IA44);
250bf215546Sopenharmony_ci      /* Same idea as above, but we have to swap the low and high nibbles.
251bf215546Sopenharmony_ci       */
252bf215546Sopenharmony_ci      for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width)
253bf215546Sopenharmony_ci         for (j = 0; j < dst_box->width; j++)
254bf215546Sopenharmony_ci            map[j * 2 + 0] = map[j * 2 + 1] = (src[j] >> 4) | (src[j] << 4);
255bf215546Sopenharmony_ci   }
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   pipe->texture_unmap(pipe, transfer);
258bf215546Sopenharmony_ci}
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ciPUBLIC
261bf215546Sopenharmony_ciStatus XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture,
262bf215546Sopenharmony_ci                            unsigned short width, unsigned short height, int xvimage_id)
263bf215546Sopenharmony_ci{
264bf215546Sopenharmony_ci   XvMCContextPrivate *context_priv;
265bf215546Sopenharmony_ci   XvMCSubpicturePrivate *subpicture_priv;
266bf215546Sopenharmony_ci   struct pipe_context *pipe;
267bf215546Sopenharmony_ci   struct pipe_resource tex_templ, *tex;
268bf215546Sopenharmony_ci   struct pipe_sampler_view sampler_templ;
269bf215546Sopenharmony_ci   enum pipe_format palette_format;
270bf215546Sopenharmony_ci   Status ret;
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture);
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   assert(dpy);
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   if (!context)
277bf215546Sopenharmony_ci      return XvMCBadContext;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   context_priv = context->privData;
280bf215546Sopenharmony_ci   pipe = context_priv->pipe;
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   if (!subpicture)
283bf215546Sopenharmony_ci      return XvMCBadSubpicture;
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   if (width > context_priv->subpicture_max_width ||
286bf215546Sopenharmony_ci       height > context_priv->subpicture_max_height)
287bf215546Sopenharmony_ci      return BadValue;
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id);
290bf215546Sopenharmony_ci   if (ret != Success)
291bf215546Sopenharmony_ci      return ret;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate));
294bf215546Sopenharmony_ci   if (!subpicture_priv)
295bf215546Sopenharmony_ci      return BadAlloc;
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_ci   memset(&tex_templ, 0, sizeof(tex_templ));
298bf215546Sopenharmony_ci   tex_templ.target = PIPE_TEXTURE_2D;
299bf215546Sopenharmony_ci   tex_templ.format = XvIDToPipe(pipe->screen, xvimage_id);
300bf215546Sopenharmony_ci   tex_templ.last_level = 0;
301bf215546Sopenharmony_ci   if (pipe->screen->get_video_param(pipe->screen,
302bf215546Sopenharmony_ci                                     PIPE_VIDEO_PROFILE_UNKNOWN,
303bf215546Sopenharmony_ci                                     PIPE_VIDEO_ENTRYPOINT_UNKNOWN,
304bf215546Sopenharmony_ci                                     PIPE_VIDEO_CAP_NPOT_TEXTURES)) {
305bf215546Sopenharmony_ci      tex_templ.width0 = width;
306bf215546Sopenharmony_ci      tex_templ.height0 = height;
307bf215546Sopenharmony_ci   }
308bf215546Sopenharmony_ci   else {
309bf215546Sopenharmony_ci      tex_templ.width0 = util_next_power_of_two(width);
310bf215546Sopenharmony_ci      tex_templ.height0 = util_next_power_of_two(height);
311bf215546Sopenharmony_ci   }
312bf215546Sopenharmony_ci   tex_templ.depth0 = 1;
313bf215546Sopenharmony_ci   tex_templ.array_size = 1;
314bf215546Sopenharmony_ci   tex_templ.usage = PIPE_USAGE_DYNAMIC;
315bf215546Sopenharmony_ci   tex_templ.bind = PIPE_BIND_SAMPLER_VIEW;
316bf215546Sopenharmony_ci   tex_templ.flags = 0;
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci   tex = pipe->screen->resource_create(pipe->screen, &tex_templ);
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   memset(&sampler_templ, 0, sizeof(sampler_templ));
321bf215546Sopenharmony_ci   u_sampler_view_default_template(&sampler_templ, tex, tex->format);
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   subpicture_priv->sampler = pipe->create_sampler_view(pipe, tex, &sampler_templ);
324bf215546Sopenharmony_ci   pipe_resource_reference(&tex, NULL);
325bf215546Sopenharmony_ci   if (!subpicture_priv->sampler) {
326bf215546Sopenharmony_ci      FREE(subpicture_priv);
327bf215546Sopenharmony_ci      return BadAlloc;
328bf215546Sopenharmony_ci   }
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci   subpicture_priv->context = context;
331bf215546Sopenharmony_ci   subpicture->subpicture_id = XAllocID(dpy);
332bf215546Sopenharmony_ci   subpicture->context_id = context->context_id;
333bf215546Sopenharmony_ci   subpicture->xvimage_id = xvimage_id;
334bf215546Sopenharmony_ci   subpicture->width = width;
335bf215546Sopenharmony_ci   subpicture->height = height;
336bf215546Sopenharmony_ci   subpicture->num_palette_entries = NumPaletteEntries4XvID(xvimage_id);
337bf215546Sopenharmony_ci   subpicture->entry_bytes = PipeToComponentOrder(
338bf215546Sopenharmony_ci         pipe->screen, tex_templ.format, &palette_format,
339bf215546Sopenharmony_ci         subpicture->component_order);
340bf215546Sopenharmony_ci   subpicture->privData = subpicture_priv;
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci   if (subpicture->num_palette_entries > 0) {
343bf215546Sopenharmony_ci      tex_templ.target = PIPE_TEXTURE_1D;
344bf215546Sopenharmony_ci      tex_templ.format = palette_format;
345bf215546Sopenharmony_ci      tex_templ.width0 = subpicture->num_palette_entries;
346bf215546Sopenharmony_ci      tex_templ.height0 = 1;
347bf215546Sopenharmony_ci      tex_templ.usage = PIPE_USAGE_DEFAULT;
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci      tex = pipe->screen->resource_create(pipe->screen, &tex_templ);
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci      memset(&sampler_templ, 0, sizeof(sampler_templ));
352bf215546Sopenharmony_ci      u_sampler_view_default_template(&sampler_templ, tex, tex->format);
353bf215546Sopenharmony_ci      sampler_templ.swizzle_a = PIPE_SWIZZLE_1;
354bf215546Sopenharmony_ci      subpicture_priv->palette = pipe->create_sampler_view(pipe, tex, &sampler_templ);
355bf215546Sopenharmony_ci      pipe_resource_reference(&tex, NULL);
356bf215546Sopenharmony_ci      if (!subpicture_priv->sampler) {
357bf215546Sopenharmony_ci         FREE(subpicture_priv);
358bf215546Sopenharmony_ci         return BadAlloc;
359bf215546Sopenharmony_ci      }
360bf215546Sopenharmony_ci   }
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   SyncHandle();
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture);
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci   return Success;
367bf215546Sopenharmony_ci}
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ciPUBLIC
370bf215546Sopenharmony_ciStatus XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y,
371bf215546Sopenharmony_ci                           unsigned short width, unsigned short height, unsigned int color)
372bf215546Sopenharmony_ci{
373bf215546Sopenharmony_ci   XvMCSubpicturePrivate *subpicture_priv;
374bf215546Sopenharmony_ci   XvMCContextPrivate *context_priv;
375bf215546Sopenharmony_ci   struct pipe_context *pipe;
376bf215546Sopenharmony_ci   struct pipe_sampler_view *dst;
377bf215546Sopenharmony_ci   struct pipe_box dst_box = {x, y, 0, width, height, 1};
378bf215546Sopenharmony_ci   struct pipe_transfer *transfer;
379bf215546Sopenharmony_ci   union util_color uc;
380bf215546Sopenharmony_ci   void *map;
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci   assert(dpy);
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci   if (!subpicture)
385bf215546Sopenharmony_ci      return XvMCBadSubpicture;
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   /* Convert color to float */
388bf215546Sopenharmony_ci   util_format_unpack_rgba(PIPE_FORMAT_B8G8R8A8_UNORM, uc.f, &color, 1);
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci   subpicture_priv = subpicture->privData;
391bf215546Sopenharmony_ci   context_priv = subpicture_priv->context->privData;
392bf215546Sopenharmony_ci   pipe = context_priv->pipe;
393bf215546Sopenharmony_ci   dst = subpicture_priv->sampler;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   /* TODO: Assert clear rect is within bounds? Or clip? */
396bf215546Sopenharmony_ci   map = pipe->texture_map(pipe, dst->texture, 0, PIPE_MAP_WRITE,
397bf215546Sopenharmony_ci                            &dst_box, &transfer);
398bf215546Sopenharmony_ci   if (!map)
399bf215546Sopenharmony_ci      return XvMCBadSubpicture;
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   util_fill_rect(map, dst->texture->format, transfer->stride, 0, 0,
402bf215546Sopenharmony_ci                  dst_box.width, dst_box.height, &uc);
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci   pipe->texture_unmap(pipe, transfer);
405bf215546Sopenharmony_ci   return Success;
406bf215546Sopenharmony_ci}
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ciPUBLIC
409bf215546Sopenharmony_ciStatus XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image,
410bf215546Sopenharmony_ci                               short srcx, short srcy, unsigned short width, unsigned short height,
411bf215546Sopenharmony_ci                               short dstx, short dsty)
412bf215546Sopenharmony_ci{
413bf215546Sopenharmony_ci   XvMCSubpicturePrivate *subpicture_priv;
414bf215546Sopenharmony_ci   XvMCContextPrivate *context_priv;
415bf215546Sopenharmony_ci   struct pipe_context *pipe;
416bf215546Sopenharmony_ci   struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1};
417bf215546Sopenharmony_ci   unsigned src_stride;
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci   XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture);
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci   assert(dpy);
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci   if (!subpicture)
424bf215546Sopenharmony_ci      return XvMCBadSubpicture;
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci   assert(image);
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci   if (subpicture->xvimage_id != image->id)
429bf215546Sopenharmony_ci      return BadMatch;
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci   /* No planar support for now */
432bf215546Sopenharmony_ci   if (image->num_planes != 1)
433bf215546Sopenharmony_ci      return BadMatch;
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci   subpicture_priv = subpicture->privData;
436bf215546Sopenharmony_ci   context_priv = subpicture_priv->context->privData;
437bf215546Sopenharmony_ci   pipe = context_priv->pipe;
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci   /* clipping should be done by upload_sampler and regardles what the documentation
440bf215546Sopenharmony_ci   says image->pitches[0] doesn't seems to be in bytes, so don't use it */
441bf215546Sopenharmony_ci   if ((image->id == FOURCC_IA44 || image->id == FOURCC_AI44) &&
442bf215546Sopenharmony_ci       subpicture_priv->sampler->texture->format == PIPE_FORMAT_B4G4R4A4_UNORM) {
443bf215546Sopenharmony_ci      upload_sampler_convert(pipe, subpicture_priv->sampler, &dst_box, image, srcx, srcy);
444bf215546Sopenharmony_ci   } else {
445bf215546Sopenharmony_ci      src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format);
446bf215546Sopenharmony_ci      upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy);
447bf215546Sopenharmony_ci   }
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   return Success;
452bf215546Sopenharmony_ci}
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ciPUBLIC
455bf215546Sopenharmony_ciStatus XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture)
456bf215546Sopenharmony_ci{
457bf215546Sopenharmony_ci   XvMCSubpicturePrivate *subpicture_priv;
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture);
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci   assert(dpy);
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci   if (!subpicture)
464bf215546Sopenharmony_ci      return XvMCBadSubpicture;
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci   subpicture_priv = subpicture->privData;
467bf215546Sopenharmony_ci   pipe_sampler_view_reference(&subpicture_priv->sampler, NULL);
468bf215546Sopenharmony_ci   pipe_sampler_view_reference(&subpicture_priv->palette, NULL);
469bf215546Sopenharmony_ci   FREE(subpicture_priv);
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture);
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   return Success;
474bf215546Sopenharmony_ci}
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ciPUBLIC
477bf215546Sopenharmony_ciStatus XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette)
478bf215546Sopenharmony_ci{
479bf215546Sopenharmony_ci   XvMCSubpicturePrivate *subpicture_priv;
480bf215546Sopenharmony_ci   XvMCContextPrivate *context_priv;
481bf215546Sopenharmony_ci   struct pipe_context *pipe;
482bf215546Sopenharmony_ci   struct pipe_box dst_box = {0, 0, 0, 0, 1, 1};
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci   assert(dpy);
485bf215546Sopenharmony_ci   assert(palette);
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci   if (!subpicture)
488bf215546Sopenharmony_ci      return XvMCBadSubpicture;
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci   subpicture_priv = subpicture->privData;
491bf215546Sopenharmony_ci   context_priv = subpicture_priv->context->privData;
492bf215546Sopenharmony_ci   pipe = context_priv->pipe;
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci   dst_box.width = subpicture->num_palette_entries;
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci   upload_sampler(pipe, subpicture_priv->palette, &dst_box, palette, 0, 0, 0);
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci   XVMC_MSG(XVMC_TRACE, "[XvMC] Palette of Subpicture %p set.\n", subpicture);
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci   return Success;
501bf215546Sopenharmony_ci}
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ciPUBLIC
504bf215546Sopenharmony_ciStatus XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture,
505bf215546Sopenharmony_ci                           short subx, short suby, unsigned short subw, unsigned short subh,
506bf215546Sopenharmony_ci                           short surfx, short surfy, unsigned short surfw, unsigned short surfh)
507bf215546Sopenharmony_ci{
508bf215546Sopenharmony_ci   struct u_rect src_rect = {subx, subx + subw, suby, suby + subh};
509bf215546Sopenharmony_ci   struct u_rect dst_rect = {surfx, surfx + surfw, surfy, surfy + surfh};
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   XvMCSurfacePrivate *surface_priv;
512bf215546Sopenharmony_ci   XvMCSubpicturePrivate *subpicture_priv;
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci   XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface);
515bf215546Sopenharmony_ci
516bf215546Sopenharmony_ci   assert(dpy);
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ci   if (!target_surface)
519bf215546Sopenharmony_ci      return XvMCBadSurface;
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci   if (!subpicture)
522bf215546Sopenharmony_ci      return XvMCBadSubpicture;
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci   if (target_surface->context_id != subpicture->context_id)
525bf215546Sopenharmony_ci      return BadMatch;
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci   /* TODO: Verify against subpicture independent scaling */
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_ci   surface_priv = target_surface->privData;
530bf215546Sopenharmony_ci   subpicture_priv = subpicture->privData;
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci   /* TODO: Assert rects are within bounds? Or clip? */
533bf215546Sopenharmony_ci   subpicture_priv->src_rect = src_rect;
534bf215546Sopenharmony_ci   subpicture_priv->dst_rect = dst_rect;
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci   surface_priv->subpicture = subpicture;
537bf215546Sopenharmony_ci   subpicture_priv->surface = target_surface;
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   return Success;
540bf215546Sopenharmony_ci}
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ciPUBLIC
543bf215546Sopenharmony_ciStatus XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface,
544bf215546Sopenharmony_ci                            XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh,
545bf215546Sopenharmony_ci                            short surfx, short surfy, unsigned short surfw, unsigned short surfh)
546bf215546Sopenharmony_ci{
547bf215546Sopenharmony_ci   assert(dpy);
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_ci   if (!source_surface || !target_surface)
550bf215546Sopenharmony_ci      return XvMCBadSurface;
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci   if (!subpicture)
553bf215546Sopenharmony_ci      return XvMCBadSubpicture;
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci   if (source_surface->context_id != subpicture->context_id)
556bf215546Sopenharmony_ci      return BadMatch;
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   if (source_surface->context_id != subpicture->context_id)
559bf215546Sopenharmony_ci      return BadMatch;
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci   /* TODO: Assert rects are within bounds? Or clip? */
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci   return Success;
564bf215546Sopenharmony_ci}
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ciPUBLIC
567bf215546Sopenharmony_ciStatus XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture)
568bf215546Sopenharmony_ci{
569bf215546Sopenharmony_ci   assert(dpy);
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci   if (!subpicture)
572bf215546Sopenharmony_ci      return XvMCBadSubpicture;
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   return Success;
575bf215546Sopenharmony_ci}
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ciPUBLIC
578bf215546Sopenharmony_ciStatus XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture)
579bf215546Sopenharmony_ci{
580bf215546Sopenharmony_ci   assert(dpy);
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci   if (!subpicture)
583bf215546Sopenharmony_ci      return XvMCBadSubpicture;
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   return Success;
586bf215546Sopenharmony_ci}
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ciPUBLIC
589bf215546Sopenharmony_ciStatus XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status)
590bf215546Sopenharmony_ci{
591bf215546Sopenharmony_ci   assert(dpy);
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci   if (!subpicture)
594bf215546Sopenharmony_ci      return XvMCBadSubpicture;
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_ci   assert(status);
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   /* TODO */
599bf215546Sopenharmony_ci   *status = 0;
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci   return Success;
602bf215546Sopenharmony_ci}
603