1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2009 Younes Manton.
4848b8605Smrg * All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg
28848b8605Smrg#include <assert.h>
29848b8605Smrg
30848b8605Smrg#include <X11/Xlibint.h>
31848b8605Smrg#include <X11/extensions/XvMClib.h>
32848b8605Smrg
33848b8605Smrg#include "pipe/p_screen.h"
34848b8605Smrg#include "pipe/p_video_codec.h"
35848b8605Smrg#include "pipe/p_state.h"
36848b8605Smrg
37848b8605Smrg#include "util/u_memory.h"
38848b8605Smrg#include "util/u_math.h"
39848b8605Smrg#include "util/u_format.h"
40848b8605Smrg#include "util/u_sampler.h"
41848b8605Smrg#include "util/u_surface.h"
42848b8605Smrg#include "util/u_rect.h"
43848b8605Smrg#include "vl/vl_winsys.h"
44848b8605Smrg
45848b8605Smrg#include "xvmc_private.h"
46848b8605Smrg
47848b8605Smrg#define FOURCC_RGB 0x0000003
48848b8605Smrg#define FOURCC_AI44 0x34344941
49848b8605Smrg#define FOURCC_IA44 0x34344149
50848b8605Smrg
51b8e80941Smrgstatic enum pipe_format XvIDToPipe(struct pipe_screen *screen,
52b8e80941Smrg                                   int xvimage_id)
53848b8605Smrg{
54b8e80941Smrg   enum pipe_format ret;
55b8e80941Smrg   assert(screen);
56848b8605Smrg
57b8e80941Smrg   switch (xvimage_id) {
58b8e80941Smrg   case FOURCC_RGB:
59b8e80941Smrg      ret = PIPE_FORMAT_B8G8R8X8_UNORM;
60b8e80941Smrg      break;
61b8e80941Smrg
62b8e80941Smrg   case FOURCC_AI44:
63b8e80941Smrg      ret = PIPE_FORMAT_R4A4_UNORM;
64b8e80941Smrg      if (!screen->is_format_supported(
65b8e80941Smrg                screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW))
66b8e80941Smrg         ret = PIPE_FORMAT_B4G4R4A4_UNORM;
67b8e80941Smrg      break;
68b8e80941Smrg
69b8e80941Smrg   case FOURCC_IA44:
70b8e80941Smrg      ret = PIPE_FORMAT_A4R4_UNORM;
71b8e80941Smrg      if (!screen->is_format_supported(
72b8e80941Smrg                screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW))
73b8e80941Smrg         ret = PIPE_FORMAT_B4G4R4A4_UNORM;
74b8e80941Smrg      break;
75b8e80941Smrg
76b8e80941Smrg   default:
77b8e80941Smrg      XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
78b8e80941Smrg      return PIPE_FORMAT_NONE;
79b8e80941Smrg   }
80848b8605Smrg
81b8e80941Smrg   if (!screen->is_format_supported(
82b8e80941Smrg             screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
83b8e80941Smrg      XVMC_MSG(XVMC_ERR, "[XvMC] Unsupported 2D format %s for Xv image ID 0x%08X.\n", util_format_name(ret), xvimage_id);
84b8e80941Smrg      ret = PIPE_FORMAT_NONE;
85848b8605Smrg   }
86b8e80941Smrg   return ret;
87b8e80941Smrg
88848b8605Smrg}
89848b8605Smrg
90848b8605Smrgstatic unsigned NumPaletteEntries4XvID(int xvimage_id)
91848b8605Smrg{
92848b8605Smrg   switch (xvimage_id) {
93848b8605Smrg      case FOURCC_RGB:
94848b8605Smrg         return 0;
95848b8605Smrg
96848b8605Smrg      case FOURCC_AI44:
97848b8605Smrg      case FOURCC_IA44:
98848b8605Smrg         return 16;
99848b8605Smrg
100848b8605Smrg      default:
101848b8605Smrg         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
102848b8605Smrg         return 0;
103848b8605Smrg   }
104848b8605Smrg}
105848b8605Smrg
106b8e80941Smrgstatic int PipeToComponentOrder(struct pipe_screen *screen,
107b8e80941Smrg                                enum pipe_format format,
108b8e80941Smrg                                enum pipe_format *palette_format,
109b8e80941Smrg                                char *component_order)
110848b8605Smrg{
111b8e80941Smrg   assert(screen);
112848b8605Smrg   assert(component_order);
113b8e80941Smrg   assert(palette_format);
114848b8605Smrg
115848b8605Smrg   switch (format) {
116b8e80941Smrg   case PIPE_FORMAT_B8G8R8X8_UNORM:
117b8e80941Smrg      return 0;
118b8e80941Smrg
119b8e80941Smrg   case PIPE_FORMAT_A4R4_UNORM:
120b8e80941Smrg   case PIPE_FORMAT_R4A4_UNORM:
121b8e80941Smrg   case PIPE_FORMAT_B4G4R4A4_UNORM:
122b8e80941Smrg      *palette_format = PIPE_FORMAT_R8G8B8X8_UNORM;
123b8e80941Smrg      component_order[0] = 'Y';
124b8e80941Smrg      component_order[1] = 'U';
125b8e80941Smrg      component_order[2] = 'V';
126b8e80941Smrg      component_order[3] = 'A';
127b8e80941Smrg      if (!screen->is_format_supported(
128b8e80941Smrg                screen, *palette_format, PIPE_TEXTURE_1D, 0, 0,
129b8e80941Smrg                PIPE_BIND_SAMPLER_VIEW)) {
130b8e80941Smrg         /* One of these formats better be supported... */
131b8e80941Smrg         *palette_format = PIPE_FORMAT_B8G8R8X8_UNORM;
132b8e80941Smrg         component_order[0] = 'V';
133b8e80941Smrg         component_order[2] = 'Y';
134b8e80941Smrg      }
135b8e80941Smrg      return 4;
136b8e80941Smrg
137b8e80941Smrg   default:
138b8e80941Smrg      XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format);
139b8e80941Smrg      component_order[0] = 0;
140b8e80941Smrg      component_order[1] = 0;
141b8e80941Smrg      component_order[2] = 0;
142b8e80941Smrg      component_order[3] = 0;
143b8e80941Smrg      return 0;
144848b8605Smrg   }
145848b8605Smrg}
146848b8605Smrg
147848b8605Smrgstatic Status Validate(Display *dpy, XvPortID port, int surface_type_id, int xvimage_id)
148848b8605Smrg{
149848b8605Smrg   XvImageFormatValues *subpictures;
150848b8605Smrg   int num_subpics;
151b8e80941Smrg   int i;
152848b8605Smrg
153848b8605Smrg   subpictures = XvMCListSubpictureTypes(dpy, port, surface_type_id, &num_subpics);
154848b8605Smrg   if (num_subpics < 1) {
155848b8605Smrg      free(subpictures);
156848b8605Smrg      return BadMatch;
157848b8605Smrg   }
158848b8605Smrg   if (!subpictures)
159848b8605Smrg      return BadAlloc;
160848b8605Smrg
161848b8605Smrg   for (i = 0; i < num_subpics; ++i) {
162848b8605Smrg      if (subpictures[i].id == xvimage_id) {
163848b8605Smrg         XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested subpicture format.\n" \
164848b8605Smrg                              "[XvMC]   port=%u\n" \
165848b8605Smrg                              "[XvMC]   surface id=0x%08X\n" \
166848b8605Smrg                              "[XvMC]   image id=0x%08X\n" \
167848b8605Smrg                              "[XvMC]   type=%08X\n" \
168848b8605Smrg                              "[XvMC]   byte order=%08X\n" \
169848b8605Smrg                              "[XvMC]   bits per pixel=%u\n" \
170848b8605Smrg                              "[XvMC]   format=%08X\n" \
171848b8605Smrg                              "[XvMC]   num planes=%d\n",
172848b8605Smrg                              port, surface_type_id, xvimage_id, subpictures[i].type, subpictures[i].byte_order,
173848b8605Smrg                              subpictures[i].bits_per_pixel, subpictures[i].format, subpictures[i].num_planes);
174848b8605Smrg         if (subpictures[i].type == XvRGB) {
175848b8605Smrg            XVMC_MSG(XVMC_TRACE, "[XvMC]   depth=%d\n" \
176848b8605Smrg                                 "[XvMC]   red mask=0x%08X\n" \
177848b8605Smrg                                 "[XvMC]   green mask=0x%08X\n" \
178848b8605Smrg                                 "[XvMC]   blue mask=0x%08X\n",
179848b8605Smrg                                 subpictures[i].depth, subpictures[i].red_mask,
180848b8605Smrg                                 subpictures[i].green_mask, subpictures[i].blue_mask);
181848b8605Smrg         }
182848b8605Smrg         else if (subpictures[i].type == XvYUV) {
183848b8605Smrg            XVMC_MSG(XVMC_TRACE, "[XvMC]   y sample bits=0x%08X\n" \
184848b8605Smrg                                 "[XvMC]   u sample bits=0x%08X\n" \
185848b8605Smrg                                 "[XvMC]   v sample bits=0x%08X\n" \
186848b8605Smrg                                 "[XvMC]   horz y period=%u\n" \
187848b8605Smrg                                 "[XvMC]   horz u period=%u\n" \
188848b8605Smrg                                 "[XvMC]   horz v period=%u\n" \
189848b8605Smrg                                 "[XvMC]   vert y period=%u\n" \
190848b8605Smrg                                 "[XvMC]   vert u period=%u\n" \
191848b8605Smrg                                 "[XvMC]   vert v period=%u\n",
192848b8605Smrg                                 subpictures[i].y_sample_bits, subpictures[i].u_sample_bits, subpictures[i].v_sample_bits,
193848b8605Smrg                                 subpictures[i].horz_y_period, subpictures[i].horz_u_period, subpictures[i].horz_v_period,
194848b8605Smrg                                 subpictures[i].vert_y_period, subpictures[i].vert_u_period, subpictures[i].vert_v_period);
195848b8605Smrg         }
196848b8605Smrg         break;
197848b8605Smrg      }
198848b8605Smrg   }
199848b8605Smrg
200848b8605Smrg   free(subpictures);
201848b8605Smrg
202848b8605Smrg   return i < num_subpics ? Success : BadMatch;
203848b8605Smrg}
204848b8605Smrg
205848b8605Smrgstatic void
206848b8605Smrgupload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst,
207848b8605Smrg               const struct pipe_box *dst_box, const void *src, unsigned src_stride,
208848b8605Smrg               unsigned src_x, unsigned src_y)
209848b8605Smrg{
210848b8605Smrg   struct pipe_transfer *transfer;
211848b8605Smrg   void *map;
212848b8605Smrg
213848b8605Smrg   map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE,
214848b8605Smrg                            dst_box, &transfer);
215848b8605Smrg   if (!map)
216848b8605Smrg      return;
217848b8605Smrg
218848b8605Smrg   util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0,
219848b8605Smrg                  dst_box->width, dst_box->height,
220848b8605Smrg                  src, src_stride, src_x, src_y);
221848b8605Smrg
222848b8605Smrg   pipe->transfer_unmap(pipe, transfer);
223848b8605Smrg}
224848b8605Smrg
225b8e80941Smrgstatic void
226b8e80941Smrgupload_sampler_convert(struct pipe_context *pipe, struct pipe_sampler_view *dst,
227b8e80941Smrg                       const struct pipe_box *dst_box, const XvImage *image,
228b8e80941Smrg                       unsigned src_x, unsigned src_y)
229b8e80941Smrg{
230b8e80941Smrg   struct pipe_transfer *transfer;
231b8e80941Smrg   int i, j;
232b8e80941Smrg   char *map, *src;
233b8e80941Smrg
234b8e80941Smrg   map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE,
235b8e80941Smrg                            dst_box, &transfer);
236b8e80941Smrg   if (!map)
237b8e80941Smrg      return;
238b8e80941Smrg
239b8e80941Smrg   src = image->data;
240b8e80941Smrg   src += src_y * image->width + src_x;
241b8e80941Smrg   if (image->id == FOURCC_AI44) {
242b8e80941Smrg      /* The format matches what we want, we just have to insert dummy
243b8e80941Smrg       * bytes. So just copy the same value in twice.
244b8e80941Smrg       */
245b8e80941Smrg      for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width)
246b8e80941Smrg         for (j = 0; j < dst_box->width; j++)
247b8e80941Smrg            map[j * 2 + 0] = map[j * 2 + 1] = src[j];
248b8e80941Smrg   } else {
249b8e80941Smrg      assert(image->id == FOURCC_IA44);
250b8e80941Smrg      /* Same idea as above, but we have to swap the low and high nibbles.
251b8e80941Smrg       */
252b8e80941Smrg      for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width)
253b8e80941Smrg         for (j = 0; j < dst_box->width; j++)
254b8e80941Smrg            map[j * 2 + 0] = map[j * 2 + 1] = (src[j] >> 4) | (src[j] << 4);
255b8e80941Smrg   }
256b8e80941Smrg
257b8e80941Smrg   pipe->transfer_unmap(pipe, transfer);
258b8e80941Smrg}
259b8e80941Smrg
260848b8605SmrgPUBLIC
261848b8605SmrgStatus XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture,
262848b8605Smrg                            unsigned short width, unsigned short height, int xvimage_id)
263848b8605Smrg{
264848b8605Smrg   XvMCContextPrivate *context_priv;
265848b8605Smrg   XvMCSubpicturePrivate *subpicture_priv;
266848b8605Smrg   struct pipe_context *pipe;
267848b8605Smrg   struct pipe_resource tex_templ, *tex;
268848b8605Smrg   struct pipe_sampler_view sampler_templ;
269b8e80941Smrg   enum pipe_format palette_format;
270848b8605Smrg   Status ret;
271848b8605Smrg
272848b8605Smrg   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture);
273848b8605Smrg
274848b8605Smrg   assert(dpy);
275848b8605Smrg
276848b8605Smrg   if (!context)
277848b8605Smrg      return XvMCBadContext;
278848b8605Smrg
279848b8605Smrg   context_priv = context->privData;
280848b8605Smrg   pipe = context_priv->pipe;
281848b8605Smrg
282848b8605Smrg   if (!subpicture)
283848b8605Smrg      return XvMCBadSubpicture;
284848b8605Smrg
285848b8605Smrg   if (width > context_priv->subpicture_max_width ||
286848b8605Smrg       height > context_priv->subpicture_max_height)
287848b8605Smrg      return BadValue;
288848b8605Smrg
289848b8605Smrg   ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id);
290848b8605Smrg   if (ret != Success)
291848b8605Smrg      return ret;
292848b8605Smrg
293848b8605Smrg   subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate));
294848b8605Smrg   if (!subpicture_priv)
295848b8605Smrg      return BadAlloc;
296848b8605Smrg
297848b8605Smrg   memset(&tex_templ, 0, sizeof(tex_templ));
298848b8605Smrg   tex_templ.target = PIPE_TEXTURE_2D;
299b8e80941Smrg   tex_templ.format = XvIDToPipe(pipe->screen, xvimage_id);
300848b8605Smrg   tex_templ.last_level = 0;
301848b8605Smrg   if (pipe->screen->get_video_param(pipe->screen,
302848b8605Smrg                                     PIPE_VIDEO_PROFILE_UNKNOWN,
303848b8605Smrg                                     PIPE_VIDEO_ENTRYPOINT_UNKNOWN,
304848b8605Smrg                                     PIPE_VIDEO_CAP_NPOT_TEXTURES)) {
305848b8605Smrg      tex_templ.width0 = width;
306848b8605Smrg      tex_templ.height0 = height;
307848b8605Smrg   }
308848b8605Smrg   else {
309848b8605Smrg      tex_templ.width0 = util_next_power_of_two(width);
310848b8605Smrg      tex_templ.height0 = util_next_power_of_two(height);
311848b8605Smrg   }
312848b8605Smrg   tex_templ.depth0 = 1;
313848b8605Smrg   tex_templ.array_size = 1;
314848b8605Smrg   tex_templ.usage = PIPE_USAGE_DYNAMIC;
315848b8605Smrg   tex_templ.bind = PIPE_BIND_SAMPLER_VIEW;
316848b8605Smrg   tex_templ.flags = 0;
317848b8605Smrg
318848b8605Smrg   tex = pipe->screen->resource_create(pipe->screen, &tex_templ);
319848b8605Smrg
320848b8605Smrg   memset(&sampler_templ, 0, sizeof(sampler_templ));
321848b8605Smrg   u_sampler_view_default_template(&sampler_templ, tex, tex->format);
322848b8605Smrg
323848b8605Smrg   subpicture_priv->sampler = pipe->create_sampler_view(pipe, tex, &sampler_templ);
324848b8605Smrg   pipe_resource_reference(&tex, NULL);
325848b8605Smrg   if (!subpicture_priv->sampler) {
326848b8605Smrg      FREE(subpicture_priv);
327848b8605Smrg      return BadAlloc;
328848b8605Smrg   }
329848b8605Smrg
330848b8605Smrg   subpicture_priv->context = context;
331848b8605Smrg   subpicture->subpicture_id = XAllocID(dpy);
332848b8605Smrg   subpicture->context_id = context->context_id;
333848b8605Smrg   subpicture->xvimage_id = xvimage_id;
334848b8605Smrg   subpicture->width = width;
335848b8605Smrg   subpicture->height = height;
336848b8605Smrg   subpicture->num_palette_entries = NumPaletteEntries4XvID(xvimage_id);
337b8e80941Smrg   subpicture->entry_bytes = PipeToComponentOrder(
338b8e80941Smrg         pipe->screen, tex_templ.format, &palette_format,
339b8e80941Smrg         subpicture->component_order);
340848b8605Smrg   subpicture->privData = subpicture_priv;
341848b8605Smrg
342848b8605Smrg   if (subpicture->num_palette_entries > 0) {
343848b8605Smrg      tex_templ.target = PIPE_TEXTURE_1D;
344b8e80941Smrg      tex_templ.format = palette_format;
345848b8605Smrg      tex_templ.width0 = subpicture->num_palette_entries;
346848b8605Smrg      tex_templ.height0 = 1;
347848b8605Smrg      tex_templ.usage = PIPE_USAGE_DEFAULT;
348848b8605Smrg
349848b8605Smrg      tex = pipe->screen->resource_create(pipe->screen, &tex_templ);
350848b8605Smrg
351848b8605Smrg      memset(&sampler_templ, 0, sizeof(sampler_templ));
352848b8605Smrg      u_sampler_view_default_template(&sampler_templ, tex, tex->format);
353b8e80941Smrg      sampler_templ.swizzle_a = PIPE_SWIZZLE_1;
354848b8605Smrg      subpicture_priv->palette = pipe->create_sampler_view(pipe, tex, &sampler_templ);
355848b8605Smrg      pipe_resource_reference(&tex, NULL);
356848b8605Smrg      if (!subpicture_priv->sampler) {
357848b8605Smrg         FREE(subpicture_priv);
358848b8605Smrg         return BadAlloc;
359848b8605Smrg      }
360848b8605Smrg   }
361848b8605Smrg
362848b8605Smrg   SyncHandle();
363848b8605Smrg
364848b8605Smrg   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture);
365848b8605Smrg
366848b8605Smrg   return Success;
367848b8605Smrg}
368848b8605Smrg
369848b8605SmrgPUBLIC
370848b8605SmrgStatus XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y,
371848b8605Smrg                           unsigned short width, unsigned short height, unsigned int color)
372848b8605Smrg{
373848b8605Smrg   XvMCSubpicturePrivate *subpicture_priv;
374848b8605Smrg   XvMCContextPrivate *context_priv;
375848b8605Smrg   struct pipe_context *pipe;
376848b8605Smrg   struct pipe_sampler_view *dst;
377848b8605Smrg   struct pipe_box dst_box = {x, y, 0, width, height, 1};
378848b8605Smrg   struct pipe_transfer *transfer;
379848b8605Smrg   union util_color uc;
380848b8605Smrg   void *map;
381848b8605Smrg
382848b8605Smrg   assert(dpy);
383848b8605Smrg
384848b8605Smrg   if (!subpicture)
385848b8605Smrg      return XvMCBadSubpicture;
386848b8605Smrg
387848b8605Smrg   /* Convert color to float */
388848b8605Smrg   util_format_read_4f(PIPE_FORMAT_B8G8R8A8_UNORM,
389848b8605Smrg                       uc.f, 1, &color, 4,
390848b8605Smrg                       0, 0, 1, 1);
391848b8605Smrg
392848b8605Smrg   subpicture_priv = subpicture->privData;
393848b8605Smrg   context_priv = subpicture_priv->context->privData;
394848b8605Smrg   pipe = context_priv->pipe;
395848b8605Smrg   dst = subpicture_priv->sampler;
396848b8605Smrg
397848b8605Smrg   /* TODO: Assert clear rect is within bounds? Or clip? */
398848b8605Smrg   map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE,
399848b8605Smrg                            &dst_box, &transfer);
400848b8605Smrg   if (!map)
401848b8605Smrg      return XvMCBadSubpicture;
402848b8605Smrg
403848b8605Smrg   util_fill_rect(map, dst->texture->format, transfer->stride, 0, 0,
404848b8605Smrg                  dst_box.width, dst_box.height, &uc);
405848b8605Smrg
406848b8605Smrg   pipe->transfer_unmap(pipe, transfer);
407848b8605Smrg   return Success;
408848b8605Smrg}
409848b8605Smrg
410848b8605SmrgPUBLIC
411848b8605SmrgStatus XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image,
412848b8605Smrg                               short srcx, short srcy, unsigned short width, unsigned short height,
413848b8605Smrg                               short dstx, short dsty)
414848b8605Smrg{
415848b8605Smrg   XvMCSubpicturePrivate *subpicture_priv;
416848b8605Smrg   XvMCContextPrivate *context_priv;
417848b8605Smrg   struct pipe_context *pipe;
418848b8605Smrg   struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1};
419848b8605Smrg   unsigned src_stride;
420848b8605Smrg
421848b8605Smrg   XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture);
422848b8605Smrg
423848b8605Smrg   assert(dpy);
424848b8605Smrg
425848b8605Smrg   if (!subpicture)
426848b8605Smrg      return XvMCBadSubpicture;
427848b8605Smrg
428848b8605Smrg   assert(image);
429848b8605Smrg
430848b8605Smrg   if (subpicture->xvimage_id != image->id)
431848b8605Smrg      return BadMatch;
432848b8605Smrg
433848b8605Smrg   /* No planar support for now */
434848b8605Smrg   if (image->num_planes != 1)
435848b8605Smrg      return BadMatch;
436848b8605Smrg
437848b8605Smrg   subpicture_priv = subpicture->privData;
438848b8605Smrg   context_priv = subpicture_priv->context->privData;
439848b8605Smrg   pipe = context_priv->pipe;
440848b8605Smrg
441848b8605Smrg   /* clipping should be done by upload_sampler and regardles what the documentation
442848b8605Smrg   says image->pitches[0] doesn't seems to be in bytes, so don't use it */
443b8e80941Smrg   if ((image->id == FOURCC_IA44 || image->id == FOURCC_AI44) &&
444b8e80941Smrg       subpicture_priv->sampler->texture->format == PIPE_FORMAT_B4G4R4A4_UNORM) {
445b8e80941Smrg      upload_sampler_convert(pipe, subpicture_priv->sampler, &dst_box, image, srcx, srcy);
446b8e80941Smrg   } else {
447b8e80941Smrg      src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format);
448b8e80941Smrg      upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy);
449b8e80941Smrg   }
450848b8605Smrg
451848b8605Smrg   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture);
452848b8605Smrg
453848b8605Smrg   return Success;
454848b8605Smrg}
455848b8605Smrg
456848b8605SmrgPUBLIC
457848b8605SmrgStatus XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture)
458848b8605Smrg{
459848b8605Smrg   XvMCSubpicturePrivate *subpicture_priv;
460848b8605Smrg
461848b8605Smrg   XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture);
462848b8605Smrg
463848b8605Smrg   assert(dpy);
464848b8605Smrg
465848b8605Smrg   if (!subpicture)
466848b8605Smrg      return XvMCBadSubpicture;
467848b8605Smrg
468848b8605Smrg   subpicture_priv = subpicture->privData;
469848b8605Smrg   pipe_sampler_view_reference(&subpicture_priv->sampler, NULL);
470848b8605Smrg   pipe_sampler_view_reference(&subpicture_priv->palette, NULL);
471848b8605Smrg   FREE(subpicture_priv);
472848b8605Smrg
473848b8605Smrg   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture);
474848b8605Smrg
475848b8605Smrg   return Success;
476848b8605Smrg}
477848b8605Smrg
478848b8605SmrgPUBLIC
479848b8605SmrgStatus XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette)
480848b8605Smrg{
481848b8605Smrg   XvMCSubpicturePrivate *subpicture_priv;
482848b8605Smrg   XvMCContextPrivate *context_priv;
483848b8605Smrg   struct pipe_context *pipe;
484848b8605Smrg   struct pipe_box dst_box = {0, 0, 0, 0, 1, 1};
485848b8605Smrg
486848b8605Smrg   assert(dpy);
487848b8605Smrg   assert(palette);
488848b8605Smrg
489848b8605Smrg   if (!subpicture)
490848b8605Smrg      return XvMCBadSubpicture;
491848b8605Smrg
492848b8605Smrg   subpicture_priv = subpicture->privData;
493848b8605Smrg   context_priv = subpicture_priv->context->privData;
494848b8605Smrg   pipe = context_priv->pipe;
495848b8605Smrg
496848b8605Smrg   dst_box.width = subpicture->num_palette_entries;
497848b8605Smrg
498848b8605Smrg   upload_sampler(pipe, subpicture_priv->palette, &dst_box, palette, 0, 0, 0);
499848b8605Smrg
500848b8605Smrg   XVMC_MSG(XVMC_TRACE, "[XvMC] Palette of Subpicture %p set.\n", subpicture);
501848b8605Smrg
502848b8605Smrg   return Success;
503848b8605Smrg}
504848b8605Smrg
505848b8605SmrgPUBLIC
506848b8605SmrgStatus XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture,
507848b8605Smrg                           short subx, short suby, unsigned short subw, unsigned short subh,
508848b8605Smrg                           short surfx, short surfy, unsigned short surfw, unsigned short surfh)
509848b8605Smrg{
510848b8605Smrg   struct u_rect src_rect = {subx, subx + subw, suby, suby + subh};
511848b8605Smrg   struct u_rect dst_rect = {surfx, surfx + surfw, surfy, surfy + surfh};
512848b8605Smrg
513848b8605Smrg   XvMCSurfacePrivate *surface_priv;
514848b8605Smrg   XvMCSubpicturePrivate *subpicture_priv;
515848b8605Smrg
516848b8605Smrg   XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface);
517848b8605Smrg
518848b8605Smrg   assert(dpy);
519848b8605Smrg
520848b8605Smrg   if (!target_surface)
521848b8605Smrg      return XvMCBadSurface;
522848b8605Smrg
523848b8605Smrg   if (!subpicture)
524848b8605Smrg      return XvMCBadSubpicture;
525848b8605Smrg
526848b8605Smrg   if (target_surface->context_id != subpicture->context_id)
527848b8605Smrg      return BadMatch;
528848b8605Smrg
529848b8605Smrg   /* TODO: Verify against subpicture independent scaling */
530848b8605Smrg
531848b8605Smrg   surface_priv = target_surface->privData;
532848b8605Smrg   subpicture_priv = subpicture->privData;
533848b8605Smrg
534848b8605Smrg   /* TODO: Assert rects are within bounds? Or clip? */
535848b8605Smrg   subpicture_priv->src_rect = src_rect;
536848b8605Smrg   subpicture_priv->dst_rect = dst_rect;
537848b8605Smrg
538848b8605Smrg   surface_priv->subpicture = subpicture;
539848b8605Smrg   subpicture_priv->surface = target_surface;
540848b8605Smrg
541848b8605Smrg   return Success;
542848b8605Smrg}
543848b8605Smrg
544848b8605SmrgPUBLIC
545848b8605SmrgStatus XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface,
546848b8605Smrg                            XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh,
547848b8605Smrg                            short surfx, short surfy, unsigned short surfw, unsigned short surfh)
548848b8605Smrg{
549848b8605Smrg   assert(dpy);
550848b8605Smrg
551848b8605Smrg   if (!source_surface || !target_surface)
552848b8605Smrg      return XvMCBadSurface;
553848b8605Smrg
554848b8605Smrg   if (!subpicture)
555848b8605Smrg      return XvMCBadSubpicture;
556848b8605Smrg
557848b8605Smrg   if (source_surface->context_id != subpicture->context_id)
558848b8605Smrg      return BadMatch;
559848b8605Smrg
560848b8605Smrg   if (source_surface->context_id != subpicture->context_id)
561848b8605Smrg      return BadMatch;
562848b8605Smrg
563848b8605Smrg   /* TODO: Assert rects are within bounds? Or clip? */
564848b8605Smrg
565848b8605Smrg   return Success;
566848b8605Smrg}
567848b8605Smrg
568848b8605SmrgPUBLIC
569848b8605SmrgStatus XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture)
570848b8605Smrg{
571848b8605Smrg   assert(dpy);
572848b8605Smrg
573848b8605Smrg   if (!subpicture)
574848b8605Smrg      return XvMCBadSubpicture;
575848b8605Smrg
576848b8605Smrg   return Success;
577848b8605Smrg}
578848b8605Smrg
579848b8605SmrgPUBLIC
580848b8605SmrgStatus XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture)
581848b8605Smrg{
582848b8605Smrg   assert(dpy);
583848b8605Smrg
584848b8605Smrg   if (!subpicture)
585848b8605Smrg      return XvMCBadSubpicture;
586848b8605Smrg
587848b8605Smrg   return Success;
588848b8605Smrg}
589848b8605Smrg
590848b8605SmrgPUBLIC
591848b8605SmrgStatus XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status)
592848b8605Smrg{
593848b8605Smrg   assert(dpy);
594848b8605Smrg
595848b8605Smrg   if (!subpicture)
596848b8605Smrg      return XvMCBadSubpicture;
597848b8605Smrg
598848b8605Smrg   assert(status);
599848b8605Smrg
600848b8605Smrg   /* TODO */
601848b8605Smrg   *status = 0;
602848b8605Smrg
603848b8605Smrg   return Success;
604848b8605Smrg}
605