e4805eae98cbb7080ba844edd7eb135c352c2224
[mesa.git] / src / gallium / auxiliary / vl / vl_context.c
1 /**************************************************************************
2 *
3 * Copyright 2009 Younes Manton.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <pipe/p_video_context.h>
29
30 #include <util/u_memory.h>
31 #include <util/u_rect.h>
32 #include <util/u_video.h>
33
34 #include "vl_context.h"
35 #include "vl_compositor.h"
36 #include "vl_mpeg12_decoder.h"
37
38 const enum pipe_format const_resource_formats_YV12[3] = {
39 PIPE_FORMAT_R8_UNORM,
40 PIPE_FORMAT_R8_UNORM,
41 PIPE_FORMAT_R8_UNORM
42 };
43
44 const enum pipe_format const_resource_formats_NV12[3] = {
45 PIPE_FORMAT_R8_UNORM,
46 PIPE_FORMAT_R8G8_UNORM,
47 PIPE_FORMAT_NONE
48 };
49
50 static void
51 vl_context_destroy(struct pipe_video_context *context)
52 {
53 struct vl_context *ctx = (struct vl_context*)context;
54
55 assert(context);
56
57 ctx->pipe->destroy(ctx->pipe);
58
59 FREE(ctx);
60 }
61
62 static int
63 vl_context_get_param(struct pipe_video_context *context, int param)
64 {
65 struct vl_context *ctx = (struct vl_context*)context;
66
67 assert(context);
68
69 if (param == PIPE_CAP_NPOT_TEXTURES)
70 return !ctx->pot_buffers;
71
72 debug_printf("vl_context: Unknown PIPE_CAP %d\n", param);
73 return 0;
74 }
75
76 static boolean
77 vl_context_is_format_supported(struct pipe_video_context *context,
78 enum pipe_format format,
79 unsigned usage)
80 {
81 struct vl_context *ctx = (struct vl_context*)context;
82
83 assert(context);
84
85 return ctx->pipe->screen->is_format_supported(ctx->pipe->screen, format,
86 PIPE_TEXTURE_2D,
87 0, usage);
88 }
89
90 static struct pipe_surface *
91 vl_context_create_surface(struct pipe_video_context *context,
92 struct pipe_resource *resource,
93 const struct pipe_surface *templ)
94 {
95 struct vl_context *ctx = (struct vl_context*)context;
96
97 assert(ctx);
98
99 return ctx->pipe->create_surface(ctx->pipe, resource, templ);
100 }
101
102 static struct pipe_sampler_view *
103 vl_context_create_sampler_view(struct pipe_video_context *context,
104 struct pipe_resource *resource,
105 const struct pipe_sampler_view *templ)
106 {
107 struct vl_context *ctx = (struct vl_context*)context;
108
109 assert(ctx);
110
111 return ctx->pipe->create_sampler_view(ctx->pipe, resource, templ);
112 }
113
114 static void
115 vl_context_upload_sampler(struct pipe_video_context *context,
116 struct pipe_sampler_view *dst,
117 const struct pipe_box *dst_box,
118 const void *src, unsigned src_stride,
119 unsigned src_x, unsigned src_y)
120 {
121 struct vl_context *ctx = (struct vl_context*)context;
122 struct pipe_transfer *transfer;
123 void *map;
124
125 assert(context);
126 assert(dst);
127 assert(dst_box);
128 assert(src);
129
130 transfer = ctx->pipe->get_transfer(ctx->pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, dst_box);
131 if (!transfer)
132 return;
133
134 map = ctx->pipe->transfer_map(ctx->pipe, transfer);
135 if (!transfer)
136 goto error_map;
137
138 util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0,
139 dst_box->width, dst_box->height,
140 src, src_stride, src_x, src_y);
141
142 ctx->pipe->transfer_unmap(ctx->pipe, transfer);
143
144 error_map:
145 ctx->pipe->transfer_destroy(ctx->pipe, transfer);
146 }
147
148 static void
149 vl_context_clear_sampler(struct pipe_video_context *context,
150 struct pipe_sampler_view *dst,
151 const struct pipe_box *dst_box,
152 const float *rgba)
153 {
154 struct vl_context *ctx = (struct vl_context*)context;
155 struct pipe_transfer *transfer;
156 union util_color uc;
157 void *map;
158 unsigned i;
159
160 assert(context);
161 assert(dst);
162 assert(dst_box);
163 assert(rgba);
164
165 transfer = ctx->pipe->get_transfer(ctx->pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, dst_box);
166 if (!transfer)
167 return;
168
169 map = ctx->pipe->transfer_map(ctx->pipe, transfer);
170 if (!transfer)
171 goto error_map;
172
173 for ( i = 0; i < 4; ++i)
174 uc.f[i] = rgba[i];
175
176 util_fill_rect(map, dst->texture->format, transfer->stride, 0, 0,
177 dst_box->width, dst_box->height, &uc);
178
179 ctx->pipe->transfer_unmap(ctx->pipe, transfer);
180
181 error_map:
182 ctx->pipe->transfer_destroy(ctx->pipe, transfer);
183 }
184
185 static struct pipe_video_decoder *
186 vl_context_create_decoder(struct pipe_video_context *context,
187 enum pipe_video_profile profile,
188 enum pipe_video_entrypoint entrypoint,
189 enum pipe_video_chroma_format chroma_format,
190 unsigned width, unsigned height)
191 {
192 struct vl_context *ctx = (struct vl_context*)context;
193 unsigned buffer_width, buffer_height;
194
195 assert(context);
196 assert(width > 0 && height > 0);
197
198 buffer_width = ctx->pot_buffers ? util_next_power_of_two(width) : align(width, MACROBLOCK_WIDTH);
199 buffer_height = ctx->pot_buffers ? util_next_power_of_two(height) : align(height, MACROBLOCK_HEIGHT);
200
201 switch (u_reduce_video_profile(profile)) {
202 case PIPE_VIDEO_CODEC_MPEG12:
203 return vl_create_mpeg12_decoder(context, ctx->pipe, profile, entrypoint,
204 chroma_format, buffer_width, buffer_height);
205 default:
206 return NULL;
207 }
208 return NULL;
209 }
210
211 static struct pipe_video_buffer *
212 vl_context_create_buffer(struct pipe_video_context *context,
213 enum pipe_format buffer_format,
214 enum pipe_video_chroma_format chroma_format,
215 unsigned width, unsigned height)
216 {
217 struct vl_context *ctx = (struct vl_context*)context;
218 struct pipe_video_buffer *result;
219 unsigned buffer_width, buffer_height;
220
221 const enum pipe_format *resource_formats;
222
223 assert(context);
224 assert(width > 0 && height > 0);
225
226 switch(buffer_format) {
227 case PIPE_FORMAT_YV12:
228 resource_formats = const_resource_formats_YV12;
229 break;
230
231 case PIPE_FORMAT_NV12:
232 resource_formats = const_resource_formats_NV12;
233 break;
234
235 default:
236 assert(0);
237 return NULL;
238 }
239
240 buffer_width = ctx->pot_buffers ? util_next_power_of_two(width) : align(width, MACROBLOCK_WIDTH);
241 buffer_height = ctx->pot_buffers ? util_next_power_of_two(height) : align(height, MACROBLOCK_HEIGHT);
242
243 result = vl_video_buffer_init(context, ctx->pipe,
244 buffer_width, buffer_height, 1,
245 chroma_format,
246 resource_formats,
247 PIPE_USAGE_STATIC);
248 if (result) // TODO move format handling into vl_video_buffer
249 result->buffer_format = buffer_format;
250
251 return result;
252 }
253
254 static struct pipe_video_compositor *
255 vl_context_create_compositor(struct pipe_video_context *context)
256 {
257 struct vl_context *ctx = (struct vl_context*)context;
258
259 assert(context);
260
261 return vl_compositor_init(context, ctx->pipe);
262 }
263
264 struct pipe_video_context *
265 vl_create_context(struct pipe_context *pipe, bool pot_buffers)
266 {
267 struct vl_context *ctx;
268
269 ctx = CALLOC_STRUCT(vl_context);
270
271 if (!ctx)
272 return NULL;
273
274 ctx->base.screen = pipe->screen;
275
276 ctx->base.destroy = vl_context_destroy;
277 ctx->base.get_param = vl_context_get_param;
278 ctx->base.is_format_supported = vl_context_is_format_supported;
279 ctx->base.create_surface = vl_context_create_surface;
280 ctx->base.create_sampler_view = vl_context_create_sampler_view;
281 ctx->base.clear_sampler = vl_context_clear_sampler;
282 ctx->base.upload_sampler = vl_context_upload_sampler;
283 ctx->base.create_decoder = vl_context_create_decoder;
284 ctx->base.create_buffer = vl_context_create_buffer;
285 ctx->base.create_compositor = vl_context_create_compositor;
286
287 ctx->pipe = pipe;
288 ctx->pot_buffers = pot_buffers;
289
290 return &ctx->base;
291 }