~thopiekar/arm-mali/libvdpau-sunxi

30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
1
/*
2
 * Copyright (c) 2013-2014 Jens Kuske <jenskuske@gmail.com>
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2.1 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17
 *
18
 */
19
20
#include <string.h>
71 by Jens Kuske
Use libcedrus
21
#include <cedrus/cedrus.h>
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
22
#include <sys/ioctl.h>
23
#include "vdpau_private.h"
24
#include "rgba.h"
72 by Andreas Baierl
Add CPU fallback for G2D
25
#include "rgba_pixman.h"
26
#include "rgba_g2d.h"
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
27
31 by Jens Kuske
Only draw/clear dirty area of output_surface
28
static void dirty_add_rect(VdpRect *dirty, const VdpRect *rect)
29
{
30
	dirty->x0 = min(dirty->x0, rect->x0);
31
	dirty->y0 = min(dirty->y0, rect->y0);
32
	dirty->x1 = max(dirty->x1, rect->x1);
33
	dirty->y1 = max(dirty->y1, rect->y1);
34
}
35
34 by Jens Kuske
Only clear rgba_surface if it won't get overwritten anyway
36
static int dirty_in_rect(const VdpRect *dirty, const VdpRect *rect)
37
{
38
	return (dirty->x0 >= rect->x0) && (dirty->y0 >= rect->y0) &&
39
	       (dirty->x1 <= rect->x1) && (dirty->y1 <= rect->y1);
40
}
41
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
42
VdpStatus rgba_create(rgba_surface_t *rgba,
43
                      device_ctx_t *device,
44
                      uint32_t width,
45
                      uint32_t height,
46
                      VdpRGBAFormat format)
47
{
48
	if (format != VDP_RGBA_FORMAT_B8G8R8A8 && format != VDP_RGBA_FORMAT_R8G8B8A8)
49
		return VDP_STATUS_INVALID_RGBA_FORMAT;
50
51
	if (width < 1 || width > 8192 || height < 1 || height > 8192)
52
		return VDP_STATUS_INVALID_SIZE;
53
54
	rgba->device = device;
55
	rgba->width = width;
56
	rgba->height = height;
57
	rgba->format = format;
58
59
	if (device->osd_enabled)
60
	{
71 by Jens Kuske
Use libcedrus
61
		rgba->data = cedrus_mem_alloc(device->cedrus, width * height * 4);
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
62
		if (!rgba->data)
63
			return VDP_STATUS_RESOURCES;
64
72 by Andreas Baierl
Add CPU fallback for G2D
65
		if(!device->g2d_enabled)
66
			vdp_pixman_ref(rgba);
67
31 by Jens Kuske
Only draw/clear dirty area of output_surface
68
		rgba->dirty.x0 = width;
69
		rgba->dirty.y0 = height;
70
		rgba->dirty.x1 = 0;
71
		rgba->dirty.y1 = 0;
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
72
		rgba_fill(rgba, NULL, 0x00000000);
73
	}
74
75
	return VDP_STATUS_OK;
76
}
77
78
void rgba_destroy(rgba_surface_t *rgba)
79
{
80
	if (rgba->device->osd_enabled)
72 by Andreas Baierl
Add CPU fallback for G2D
81
	{
82
		if(!rgba->device->g2d_enabled)
83
			vdp_pixman_unref(rgba);
84
71 by Jens Kuske
Use libcedrus
85
		cedrus_mem_free(rgba->data);
72 by Andreas Baierl
Add CPU fallback for G2D
86
	}
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
87
}
88
89
VdpStatus rgba_put_bits_native(rgba_surface_t *rgba,
90
                               void const *const *source_data,
91
                               uint32_t const *source_pitches,
92
                               VdpRect const *destination_rect)
93
{
94
	if (!rgba->device->osd_enabled)
95
		return VDP_STATUS_OK;
96
97
	VdpRect d_rect = {0, 0, rgba->width, rgba->height};
98
	if (destination_rect)
99
		d_rect = *destination_rect;
100
34 by Jens Kuske
Only clear rgba_surface if it won't get overwritten anyway
101
	if ((rgba->flags & RGBA_FLAG_NEEDS_CLEAR) && !dirty_in_rect(&rgba->dirty, &d_rect))
102
		rgba_clear(rgba);
103
55 by Jens Kuske
Fix rgba_put_bits_native full width optimization
104
	if (0 == d_rect.x0 && rgba->width == d_rect.x1 && source_pitches[0] == d_rect.x1 * 4) {
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
105
		// full width
106
		const int bytes_to_copy =
107
			(d_rect.x1 - d_rect.x0) * (d_rect.y1 - d_rect.y0) * 4;
71 by Jens Kuske
Use libcedrus
108
		memcpy(cedrus_mem_get_pointer(rgba->data) + d_rect.y0 * rgba->width * 4,
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
109
			   source_data[0], bytes_to_copy);
110
	} else {
111
		const unsigned int bytes_in_line = (d_rect.x1-d_rect.x0) * 4;
112
		unsigned int y;
113
		for (y = d_rect.y0; y < d_rect.y1; y ++) {
71 by Jens Kuske
Use libcedrus
114
			memcpy(cedrus_mem_get_pointer(rgba->data) + (y * rgba->width + d_rect.x0) * 4,
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
115
				   source_data[0] + (y - d_rect.y0) * source_pitches[0],
116
				   bytes_in_line);
117
		}
118
	}
119
34 by Jens Kuske
Only clear rgba_surface if it won't get overwritten anyway
120
	rgba->flags &= ~RGBA_FLAG_NEEDS_CLEAR;
32 by Jens Kuske
Only flush cache of rgba_surface data when needed
121
	rgba->flags |= RGBA_FLAG_DIRTY | RGBA_FLAG_NEEDS_FLUSH;
31 by Jens Kuske
Only draw/clear dirty area of output_surface
122
	dirty_add_rect(&rgba->dirty, &d_rect);
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
123
124
	return VDP_STATUS_OK;
125
}
126
127
VdpStatus rgba_put_bits_indexed(rgba_surface_t *rgba,
128
                                VdpIndexedFormat source_indexed_format,
129
                                void const *const *source_data,
130
                                uint32_t const *source_pitch,
131
                                VdpRect const *destination_rect,
132
                                VdpColorTableFormat color_table_format,
133
                                void const *color_table)
134
{
135
	if (color_table_format != VDP_COLOR_TABLE_FORMAT_B8G8R8X8)
136
		return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
137
138
	if (!rgba->device->osd_enabled)
139
		return VDP_STATUS_OK;
140
31 by Jens Kuske
Only draw/clear dirty area of output_surface
141
	int x, y;
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
142
	const uint32_t *colormap = color_table;
143
	const uint8_t *src_ptr = source_data[0];
71 by Jens Kuske
Use libcedrus
144
	uint32_t *dst_ptr = cedrus_mem_get_pointer(rgba->data);
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
145
31 by Jens Kuske
Only draw/clear dirty area of output_surface
146
	VdpRect d_rect = {0, 0, rgba->width, rgba->height};
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
147
	if (destination_rect)
31 by Jens Kuske
Only draw/clear dirty area of output_surface
148
		d_rect = *destination_rect;
149
34 by Jens Kuske
Only clear rgba_surface if it won't get overwritten anyway
150
	if ((rgba->flags & RGBA_FLAG_NEEDS_CLEAR) && !dirty_in_rect(&rgba->dirty, &d_rect))
151
		rgba_clear(rgba);
152
31 by Jens Kuske
Only draw/clear dirty area of output_surface
153
	dst_ptr += d_rect.y0 * rgba->width;
154
	dst_ptr += d_rect.x0;
155
156
	for (y = 0; y < d_rect.y1 - d_rect.y0; y++)
157
	{
158
		for (x = 0; x < d_rect.x1 - d_rect.x0; x++)
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
159
		{
160
			uint8_t i, a;
161
			switch (source_indexed_format)
162
			{
163
			case VDP_INDEXED_FORMAT_I8A8:
164
				i = src_ptr[x * 2];
165
				a = src_ptr[x * 2 + 1];
166
				break;
167
			case VDP_INDEXED_FORMAT_A8I8:
168
				a = src_ptr[x * 2];
169
				i = src_ptr[x * 2 + 1];
170
				break;
171
			default:
172
				return VDP_STATUS_INVALID_INDEXED_FORMAT;
173
			}
174
			dst_ptr[x] = (colormap[i] & 0x00ffffff) | (a << 24);
175
		}
176
		src_ptr += source_pitch[0];
177
		dst_ptr += rgba->width;
178
	}
179
34 by Jens Kuske
Only clear rgba_surface if it won't get overwritten anyway
180
	rgba->flags &= ~RGBA_FLAG_NEEDS_CLEAR;
32 by Jens Kuske
Only flush cache of rgba_surface data when needed
181
	rgba->flags |= RGBA_FLAG_DIRTY | RGBA_FLAG_NEEDS_FLUSH;
31 by Jens Kuske
Only draw/clear dirty area of output_surface
182
	dirty_add_rect(&rgba->dirty, &d_rect);
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
183
184
	return VDP_STATUS_OK;
185
}
186
187
VdpStatus rgba_render_surface(rgba_surface_t *dest,
188
                              VdpRect const *destination_rect,
189
                              rgba_surface_t *src,
190
                              VdpRect const *source_rect,
191
                              VdpColor const *colors,
192
                              VdpOutputSurfaceRenderBlendState const *blend_state,
193
                              uint32_t flags)
194
{
195
	if (!dest->device->osd_enabled)
196
		return VDP_STATUS_OK;
197
198
	if (colors || flags)
199
		VDPAU_DBG_ONCE("%s: colors and flags not implemented!", __func__);
200
201
	// set up source/destination rects using defaults where required
202
	VdpRect s_rect = {0, 0, 0, 0};
203
	VdpRect d_rect = {0, 0, dest->width, dest->height};
204
	s_rect.x1 = src ? src->width : 1;
205
	s_rect.y1 = src ? src->height : 1;
206
207
	if (source_rect)
208
		s_rect = *source_rect;
209
	if (destination_rect)
210
		d_rect = *destination_rect;
211
33 by Jens Kuske
Ignore zero-sized surfaces in rgba_render_surface
212
	// ignore zero-sized surfaces (also workaround for g2d driver bug)
213
	if (s_rect.x0 == s_rect.x1 || s_rect.y0 == s_rect.y1 ||
214
	    d_rect.x0 == d_rect.x1 || d_rect.y0 == d_rect.y1)
215
		return VDP_STATUS_OK;
216
34 by Jens Kuske
Only clear rgba_surface if it won't get overwritten anyway
217
	if ((dest->flags & RGBA_FLAG_NEEDS_CLEAR) && !dirty_in_rect(&dest->dirty, &d_rect))
218
		rgba_clear(dest);
219
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
220
	if (!src)
221
		rgba_fill(dest, &d_rect, 0xffffffff);
222
	else
223
		rgba_blit(dest, &d_rect, src, &s_rect);
224
34 by Jens Kuske
Only clear rgba_surface if it won't get overwritten anyway
225
	dest->flags &= ~RGBA_FLAG_NEEDS_CLEAR;
31 by Jens Kuske
Only draw/clear dirty area of output_surface
226
	dest->flags |= RGBA_FLAG_DIRTY;
227
	dirty_add_rect(&dest->dirty, &d_rect);
228
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
229
	return VDP_STATUS_OK;
230
}
231
31 by Jens Kuske
Only draw/clear dirty area of output_surface
232
void rgba_clear(rgba_surface_t *rgba)
233
{
234
	if (!(rgba->flags & RGBA_FLAG_DIRTY))
235
		return;
236
237
	rgba_fill(rgba, &rgba->dirty, 0x00000000);
41 by rellla
Fix typo in rgba.c
238
	rgba->flags &= ~(RGBA_FLAG_DIRTY | RGBA_FLAG_NEEDS_CLEAR);
31 by Jens Kuske
Only draw/clear dirty area of output_surface
239
	rgba->dirty.x0 = rgba->width;
240
	rgba->dirty.y0 = rgba->height;
241
	rgba->dirty.x1 = 0;
242
	rgba->dirty.y1 = 0;
243
}
244
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
245
void rgba_fill(rgba_surface_t *dest, const VdpRect *dest_rect, uint32_t color)
246
{
247
	if (dest->device->osd_enabled)
248
	{
72 by Andreas Baierl
Add CPU fallback for G2D
249
		if(dest->device->g2d_enabled)
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
250
		{
72 by Andreas Baierl
Add CPU fallback for G2D
251
			rgba_flush(dest);
252
			g2d_fill(dest, dest_rect, color);
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
253
		}
254
		else
255
		{
72 by Andreas Baierl
Add CPU fallback for G2D
256
			vdp_pixman_fill(dest, dest_rect, color);
257
			dest->flags |= RGBA_FLAG_NEEDS_FLUSH;
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
258
		}
259
	}
260
}
261
262
void rgba_blit(rgba_surface_t *dest, const VdpRect *dest_rect, rgba_surface_t *src, const VdpRect *src_rect)
263
{
264
	if (dest->device->osd_enabled)
265
	{
72 by Andreas Baierl
Add CPU fallback for G2D
266
		if(dest->device->g2d_enabled)
267
		{
268
			rgba_flush(dest);
269
			rgba_flush(src);
270
			g2d_blit(dest, dest_rect, src, src_rect);
271
		}
272
		else
273
		{
274
			vdp_pixman_blit(dest, dest_rect, src, src_rect);
275
			dest->flags |= RGBA_FLAG_NEEDS_FLUSH;
276
		}
30 by Jens Kuske
Merge common parts of bitmap_surface and output_surface into rgba_surface
277
	}
278
}
32 by Jens Kuske
Only flush cache of rgba_surface data when needed
279
280
void rgba_flush(rgba_surface_t *rgba)
281
{
282
	if (rgba->flags & RGBA_FLAG_NEEDS_FLUSH)
283
	{
71 by Jens Kuske
Use libcedrus
284
		cedrus_mem_flush_cache(rgba->data);
32 by Jens Kuske
Only flush cache of rgba_surface data when needed
285
		rgba->flags &= ~RGBA_FLAG_NEEDS_FLUSH;
286
	}
287
}