src/video/ps2gs/SDL_gsyuv.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 17 Apr 2006 06:47:23 +0000
changeset 1643 51038e80ae59
parent 1402 d910939febfa
child 1659 14717b52abc0
permissions -rw-r--r--
More general fix for bug #189

The clipping is done at a higher level, and the low level functions are
passed clipped rectangles. Drivers which don't support source clipping
have not been changed, so the image will be squished instead of clipped,
but at least they will no longer crash when the destination rect was out
of bounds.
slouken@70
     1
/*
slouken@70
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@70
     4
slouken@70
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@70
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@70
     9
slouken@70
    10
    This library is distributed in the hope that it will be useful,
slouken@70
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@70
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@70
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@70
    18
slouken@70
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@70
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@70
    23
slouken@70
    24
/* This is the Playstation 2 implementation of YUV video overlays */
slouken@70
    25
slouken@70
    26
#include <fcntl.h>
slouken@70
    27
#include <unistd.h>
slouken@70
    28
#include <sys/ioctl.h>
slouken@70
    29
#include <sys/mman.h>
slouken@70
    30
#include <asm/page.h>		/* For definition of PAGE_SIZE */
slouken@70
    31
slouken@70
    32
#include "SDL_video.h"
slouken@70
    33
#include "SDL_gsyuv_c.h"
slouken@1361
    34
#include "../SDL_yuvfuncs.h"
slouken@70
    35
slouken@70
    36
/* The maximum number of 16x16 pixel block converted at once */
slouken@70
    37
#define MAX_MACROBLOCKS	1024	/* 2^10 macroblocks at once */
slouken@70
    38
slouken@70
    39
/* The functions used to manipulate video overlays */
slouken@70
    40
static struct private_yuvhwfuncs gs_yuvfuncs = {
slouken@70
    41
	GS_LockYUVOverlay,
slouken@70
    42
	GS_UnlockYUVOverlay,
slouken@70
    43
	GS_DisplayYUVOverlay,
slouken@70
    44
	GS_FreeYUVOverlay
slouken@70
    45
};
slouken@70
    46
slouken@70
    47
struct private_yuvhwdata {
slouken@70
    48
	int ipu_fd;
slouken@70
    49
	Uint8 *pixels;
slouken@70
    50
	int macroblocks;
slouken@70
    51
	int dma_len;
slouken@70
    52
	caddr_t dma_mem;
slouken@70
    53
	caddr_t ipu_imem;
slouken@70
    54
	caddr_t ipu_omem;
slouken@70
    55
	caddr_t dma_tags;
slouken@70
    56
	unsigned long long *stretch_x1y1;
slouken@70
    57
	unsigned long long *stretch_x2y2;
slouken@70
    58
	struct ps2_plist plist;
slouken@70
    59
slouken@70
    60
	/* These are just so we don't have to allocate them separately */
slouken@70
    61
	Uint16 pitches[3];
slouken@70
    62
	Uint8 *planes[3];
slouken@70
    63
};
slouken@70
    64
slouken@70
    65
static int power_of_2(int value)
slouken@70
    66
{
slouken@70
    67
	int shift;
slouken@70
    68
slouken@70
    69
	for ( shift = 0; (1<<shift) < value; ++shift ) {
slouken@70
    70
		/* Keep looking */ ;
slouken@70
    71
	}
slouken@70
    72
	return(shift);
slouken@70
    73
}
slouken@70
    74
slouken@70
    75
SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
slouken@70
    76
{
slouken@70
    77
	SDL_Overlay *overlay;
slouken@70
    78
	struct private_yuvhwdata *hwdata;
slouken@70
    79
	int map_offset;
slouken@70
    80
	unsigned long long *tags;
slouken@70
    81
	caddr_t base;
slouken@70
    82
	int bpp;
slouken@70
    83
	int fbp, fbw, psm;
slouken@70
    84
	int x, y, w, h;
slouken@70
    85
	int pnum;
slouken@70
    86
	struct ps2_packet *packet;
slouken@70
    87
	struct ps2_packet tex_packet;
slouken@70
    88
slouken@70
    89
	/* We can only decode blocks of 16x16 pixels */
slouken@70
    90
	if ( (width & 15) || (height & 15) ) {
slouken@70
    91
		SDL_SetError("Overlay width/height must be multiples of 16");
slouken@70
    92
		return(NULL);
slouken@70
    93
	}
slouken@70
    94
	/* Make sure the image isn't too large for a single DMA transfer */
slouken@70
    95
	if ( ((width/16) * (height/16)) > MAX_MACROBLOCKS ) {
slouken@70
    96
		SDL_SetError("Overlay too large (maximum size: %d pixels)",
slouken@70
    97
		             MAX_MACROBLOCKS * 16 * 16);
slouken@70
    98
		return(NULL);
slouken@70
    99
	}
slouken@70
   100
slouken@70
   101
	/* Double-check the requested format.  For simplicity, we'll only
slouken@70
   102
	   support planar YUV formats.
slouken@70
   103
	 */
slouken@70
   104
	switch (format) {
slouken@70
   105
	    case SDL_YV12_OVERLAY:
slouken@70
   106
	    case SDL_IYUV_OVERLAY:
slouken@70
   107
		/* Supported planar YUV format */
slouken@70
   108
		break;
slouken@70
   109
	    default:
slouken@70
   110
		SDL_SetError("Unsupported YUV format");
slouken@70
   111
		return(NULL);
slouken@70
   112
	}
slouken@70
   113
slouken@70
   114
	/* Create the overlay structure */
slouken@1336
   115
	overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay);
slouken@70
   116
	if ( overlay == NULL ) {
slouken@70
   117
		SDL_OutOfMemory();
slouken@70
   118
		return(NULL);
slouken@70
   119
	}
slouken@1336
   120
	SDL_memset(overlay, 0, (sizeof *overlay));
slouken@70
   121
slouken@70
   122
	/* Fill in the basic members */
slouken@70
   123
	overlay->format = format;
slouken@70
   124
	overlay->w = width;
slouken@70
   125
	overlay->h = height;
slouken@70
   126
slouken@70
   127
	/* Set up the YUV surface function structure */
slouken@70
   128
	overlay->hwfuncs = &gs_yuvfuncs;
slouken@70
   129
	overlay->hw_overlay = 1;
slouken@70
   130
slouken@70
   131
	/* Create the pixel data */
slouken@1336
   132
	hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata);
slouken@70
   133
	overlay->hwdata = hwdata;
slouken@70
   134
	if ( hwdata == NULL ) {
slouken@70
   135
		SDL_FreeYUVOverlay(overlay);
slouken@70
   136
		SDL_OutOfMemory();
slouken@70
   137
		return(NULL);
slouken@70
   138
	}
slouken@70
   139
	hwdata->ipu_fd = -1;
slouken@1336
   140
	hwdata->pixels = (Uint8 *)SDL_malloc(width*height*2);
slouken@70
   141
	if ( hwdata->pixels == NULL ) {
slouken@70
   142
		SDL_FreeYUVOverlay(overlay);
slouken@70
   143
		SDL_OutOfMemory();
slouken@70
   144
		return(NULL);
slouken@70
   145
	}
slouken@70
   146
	hwdata->macroblocks = (width/16) * (height/16);
slouken@70
   147
slouken@70
   148
	/* Find the pitch and offset values for the overlay */
slouken@70
   149
	overlay->pitches = hwdata->pitches;
slouken@70
   150
	overlay->pixels = hwdata->planes;
slouken@70
   151
	switch (format) {
slouken@70
   152
	    case SDL_YV12_OVERLAY:
slouken@70
   153
	    case SDL_IYUV_OVERLAY:
slouken@70
   154
		overlay->pitches[0] = overlay->w;
slouken@70
   155
		overlay->pitches[1] = overlay->pitches[0] / 2;
slouken@70
   156
		overlay->pitches[2] = overlay->pitches[0] / 2;
slouken@70
   157
	        overlay->pixels[0] = hwdata->pixels;
slouken@70
   158
	        overlay->pixels[1] = overlay->pixels[0] +
slouken@70
   159
		                     overlay->pitches[0] * overlay->h;
slouken@70
   160
	        overlay->pixels[2] = overlay->pixels[1] +
slouken@70
   161
		                     overlay->pitches[1] * overlay->h / 2;
slouken@70
   162
		overlay->planes = 3;
slouken@70
   163
		break;
slouken@70
   164
	    default:
slouken@70
   165
		/* We should never get here (caught above) */
slouken@70
   166
		break;
slouken@70
   167
	}
slouken@70
   168
slouken@70
   169
	/* Theoretically we could support several concurrent decode
slouken@70
   170
	   streams queueing up on the same file descriptor, but for
slouken@70
   171
	   simplicity we'll support only one.  Opening the IPU more
slouken@70
   172
	   than once will fail with EBUSY.
slouken@70
   173
	*/
slouken@70
   174
	hwdata->ipu_fd = open("/dev/ps2ipu", O_RDWR);
slouken@70
   175
	if ( hwdata->ipu_fd < 0 ) {
slouken@70
   176
		SDL_FreeYUVOverlay(overlay);
slouken@70
   177
		SDL_SetError("Playstation 2 IPU busy");
slouken@70
   178
		return(NULL);
slouken@70
   179
	}
slouken@70
   180
slouken@70
   181
	/* Allocate a DMA area for pixel conversion */
slouken@70
   182
	bpp = this->screen->format->BytesPerPixel;
slouken@70
   183
	map_offset = (mapped_len + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
slouken@70
   184
	hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) +
slouken@70
   185
	                  width * height * bpp +
slouken@70
   186
	                  hwdata->macroblocks * (16 * sizeof(long long)) +
slouken@70
   187
	                  12 * sizeof(long long);
slouken@70
   188
	hwdata->dma_mem = mmap(0, hwdata->dma_len, PROT_READ|PROT_WRITE,
slouken@70
   189
	                       MAP_SHARED, memory_fd, map_offset);
slouken@70
   190
	if ( hwdata->dma_mem == MAP_FAILED ) {
slouken@70
   191
		hwdata->ipu_imem = (caddr_t)0;
slouken@70
   192
		SDL_FreeYUVOverlay(overlay);
slouken@70
   193
		SDL_SetError("Unable to map %d bytes for DMA", hwdata->dma_len);
slouken@70
   194
		return(NULL);
slouken@70
   195
	}
slouken@70
   196
	hwdata->ipu_imem = hwdata->dma_mem;
slouken@70
   197
	hwdata->ipu_omem = hwdata->ipu_imem +
slouken@70
   198
	                   hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
slouken@70
   199
	hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp;
slouken@70
   200
slouken@70
   201
	/* Allocate memory for the DMA packets */
slouken@70
   202
	hwdata->plist.num = hwdata->macroblocks * 4 + 1;
slouken@1336
   203
	hwdata->plist.packet = (struct ps2_packet *)SDL_malloc(
slouken@70
   204
	                       hwdata->plist.num*sizeof(struct ps2_packet));
slouken@70
   205
	if ( ! hwdata->plist.packet ) {
slouken@70
   206
		SDL_FreeYUVOverlay(overlay);
slouken@70
   207
		SDL_OutOfMemory();
slouken@70
   208
		return(NULL);
slouken@70
   209
	}
slouken@70
   210
	pnum = 0;
slouken@70
   211
	packet = hwdata->plist.packet;
slouken@70
   212
slouken@70
   213
	/* Set up the tags to send the image to the screen */
slouken@70
   214
	tags = (unsigned long long *)hwdata->dma_tags;
slouken@70
   215
	base = hwdata->ipu_omem;
slouken@70
   216
	fbp = screen_image.fbp;
slouken@70
   217
	fbw = screen_image.fbw;
slouken@70
   218
	psm = screen_image.psm;
slouken@136
   219
	y = screen_image.y + screen_image.h;	/* Offscreen video memory */
slouken@70
   220
	for ( h=height/16; h; --h ) {
slouken@70
   221
		x = 0;			/* Visible video memory */
slouken@70
   222
		for ( w=width/16; w; --w ) {
slouken@70
   223
			/* The head tag */
slouken@70
   224
			packet[pnum].ptr = &tags[0];
slouken@70
   225
			packet[pnum].len = 10 * sizeof(*tags);
slouken@70
   226
			++pnum;
slouken@70
   227
			tags[0] = 4 | (1LL << 60);	/* GIFtag */
slouken@70
   228
			tags[1] = 0x0e;			/* A+D */
slouken@70
   229
			tags[2] = ((unsigned long long)fbp << 32) |
slouken@70
   230
			          ((unsigned long long)fbw << 48) |
slouken@70
   231
			          ((unsigned long long)psm << 56);
slouken@70
   232
			tags[3] = PS2_GS_BITBLTBUF;
slouken@70
   233
			tags[4] = ((unsigned long long)x << 32) |
slouken@70
   234
			          ((unsigned long long)y << 48);
slouken@70
   235
			tags[5] = PS2_GS_TRXPOS;
slouken@70
   236
			tags[6] = (unsigned long long)16 |
slouken@70
   237
			          ((unsigned long long)16 << 32);
slouken@70
   238
			tags[7] = PS2_GS_TRXREG;
slouken@70
   239
			tags[8] = 0;
slouken@70
   240
			tags[9] = PS2_GS_TRXDIR;
slouken@70
   241
			/* Now the actual image data */
slouken@70
   242
			packet[pnum].ptr = &tags[10];
slouken@70
   243
			packet[pnum].len = 2 * sizeof(*tags);
slouken@70
   244
			++pnum;
slouken@70
   245
			tags[10] = ((16*16*bpp) >> 4) | (2LL << 58);
slouken@70
   246
			tags[11] = 0;
slouken@70
   247
			packet[pnum].ptr = (void *)base;
slouken@70
   248
			packet[pnum].len = 16 * 16 * bpp;
slouken@70
   249
			++pnum;
slouken@70
   250
			packet[pnum].ptr = &tags[12];
slouken@70
   251
			packet[pnum].len = 2 * sizeof(*tags);
slouken@70
   252
			++pnum;
slouken@70
   253
			tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58);
slouken@70
   254
			tags[13] = 0;
slouken@70
   255
slouken@70
   256
			tags += 16;
slouken@70
   257
			base += 16 * 16 * bpp;
slouken@70
   258
slouken@70
   259
			x += 16;
slouken@70
   260
		}
slouken@70
   261
		y += 16;
slouken@70
   262
	}
slouken@70
   263
slouken@70
   264
	/* Set up the texture memory area for the video */
slouken@70
   265
	tex_packet.ptr = tags;
slouken@70
   266
	tex_packet.len = 8 * sizeof(*tags);
slouken@70
   267
	tags[0] = 3 | (1LL << 60);	/* GIFtag */
slouken@70
   268
	tags[1] = 0x0e;			/* A+D */
slouken@136
   269
	tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 +
slouken@70
   270
	          ((unsigned long long)fbw << 14) +
slouken@70
   271
	          ((unsigned long long)psm << 20) +
slouken@70
   272
	          ((unsigned long long)power_of_2(width) << 26) +
slouken@70
   273
	          ((unsigned long long)power_of_2(height) << 30) +
slouken@70
   274
	          ((unsigned long long)1 << 34) +
slouken@70
   275
	          ((unsigned long long)1 << 35);
slouken@70
   276
	tags[3] = PS2_GS_TEX0_1;
slouken@70
   277
	tags[4] = (1 << 5) + (1 << 6);
slouken@70
   278
	tags[5] = PS2_GS_TEX1_1;
slouken@70
   279
	tags[6] = 0;
slouken@70
   280
	tags[7] = PS2_GS_TEXFLUSH;
slouken@70
   281
	ioctl(console_fd, PS2IOC_SEND, &tex_packet);
slouken@70
   282
slouken@70
   283
	/* Set up the tags for scaling the image */
slouken@70
   284
	packet[pnum].ptr = tags;
slouken@70
   285
	packet[pnum].len = 12 * sizeof(*tags);
slouken@70
   286
	++pnum;
slouken@70
   287
	tags[0] = 5 | (1LL << 60);	/* GIFtag */
slouken@70
   288
	tags[1] = 0x0e;			/* A+D */
slouken@70
   289
	tags[2] = 6 + (1 << 4) + (1 << 8);
slouken@70
   290
	tags[3] = PS2_GS_PRIM;
slouken@70
   291
	tags[4] = ((unsigned long long)0 * 16) +
slouken@70
   292
	           (((unsigned long long)0 * 16) << 16);
slouken@70
   293
	tags[5] = PS2_GS_UV;
slouken@70
   294
	tags[6] = 0; /* X1, Y1 */
slouken@70
   295
	tags[7] = PS2_GS_XYZ2;
slouken@70
   296
	hwdata->stretch_x1y1 = &tags[6];
slouken@70
   297
	tags[8] = ((unsigned long long)overlay->w * 16) +
slouken@70
   298
	           (((unsigned long long)overlay->h * 16) << 16);
slouken@70
   299
	tags[9] = PS2_GS_UV;
slouken@70
   300
	tags[10] = 0; /* X2, Y2 */
slouken@70
   301
	tags[11] = PS2_GS_XYZ2;
slouken@70
   302
	hwdata->stretch_x2y2 = &tags[10];
slouken@70
   303
slouken@70
   304
	/* We're all done.. */
slouken@70
   305
	return(overlay);
slouken@70
   306
}
slouken@70
   307
slouken@70
   308
int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay)
slouken@70
   309
{
slouken@70
   310
	return(0);
slouken@70
   311
}
slouken@70
   312
slouken@70
   313
void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay)
slouken@70
   314
{
slouken@70
   315
	return;
slouken@70
   316
}
slouken@70
   317
slouken@1643
   318
int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst)
slouken@70
   319
{
slouken@70
   320
	struct private_yuvhwdata *hwdata;
slouken@70
   321
	__u32 cmd;
slouken@70
   322
	struct ps2_packet packet;
slouken@70
   323
	int h, w, i;
slouken@70
   324
	Uint32 *lum, *Cr, *Cb;
slouken@70
   325
	int lum_pitch;
slouken@70
   326
	int crb_pitch;
slouken@70
   327
	Uint32 *lum_src, *Cr_src, *Cb_src;
slouken@70
   328
	Uint32 *src, *dst;
slouken@70
   329
	unsigned int x, y;
slouken@70
   330
	SDL_Surface *screen;
slouken@70
   331
slouken@70
   332
	/* Find out where the various portions of the image are */
slouken@70
   333
	hwdata = overlay->hwdata;
slouken@70
   334
	switch (overlay->format) {
slouken@70
   335
	    case SDL_YV12_OVERLAY:
slouken@70
   336
		lum = (Uint32 *)overlay->pixels[0];
slouken@70
   337
		Cr =  (Uint32 *)overlay->pixels[1];
slouken@70
   338
		Cb =  (Uint32 *)overlay->pixels[2];
slouken@70
   339
		break;
slouken@70
   340
	    case SDL_IYUV_OVERLAY:
slouken@70
   341
		lum = (Uint32 *)overlay->pixels[0];
slouken@70
   342
		Cr =  (Uint32 *)overlay->pixels[2];
slouken@70
   343
		Cb =  (Uint32 *)overlay->pixels[1];
slouken@70
   344
	    default:
slouken@543
   345
		SDL_SetError("Unsupported YUV format in blit (?)");
slouken@70
   346
		return(-1);
slouken@70
   347
	}
slouken@70
   348
	dst = (Uint32 *)hwdata->ipu_imem;
slouken@70
   349
	lum_pitch = overlay->w/4;
slouken@70
   350
	crb_pitch = (overlay->w/2)/4;
slouken@70
   351
slouken@70
   352
	/* Copy blocks of 16x16 pixels to the DMA area */
slouken@70
   353
	for ( h=overlay->h/16; h; --h ) {
slouken@70
   354
		lum_src = lum;
slouken@70
   355
		Cr_src = Cr;
slouken@70
   356
		Cb_src = Cb;
slouken@70
   357
		for ( w=overlay->w/16; w; --w ) {
slouken@70
   358
			src = lum_src;
slouken@70
   359
			for ( i=0; i<16; ++i ) {
slouken@70
   360
				dst[0] = src[0];
slouken@70
   361
				dst[1] = src[1];
slouken@70
   362
				dst[2] = src[2];
slouken@70
   363
				dst[3] = src[3];
slouken@70
   364
				src += lum_pitch;
slouken@70
   365
				dst += 4;
slouken@70
   366
			}
slouken@70
   367
			src = Cb_src;
slouken@70
   368
			for ( i=0; i<8; ++i ) {
slouken@70
   369
				dst[0] = src[0];
slouken@70
   370
				dst[1] = src[1];
slouken@70
   371
				src += crb_pitch;
slouken@70
   372
				dst += 2;
slouken@70
   373
			}
slouken@70
   374
			src = Cr_src;
slouken@70
   375
			for ( i=0; i<8; ++i ) {
slouken@70
   376
				dst[0] = src[0];
slouken@70
   377
				dst[1] = src[1];
slouken@70
   378
				src += crb_pitch;
slouken@70
   379
				dst += 2;
slouken@70
   380
			}
slouken@70
   381
			lum_src += 16 / 4;
slouken@70
   382
			Cb_src += 8 / 4;
slouken@70
   383
			Cr_src += 8 / 4;
slouken@70
   384
		}
slouken@70
   385
		lum += lum_pitch * 16;
slouken@70
   386
		Cr += crb_pitch * 8;
slouken@70
   387
		Cb += crb_pitch * 8;
slouken@70
   388
	}
slouken@70
   389
slouken@70
   390
	/* Send the macroblock data to the IPU */
slouken@70
   391
#ifdef DEBUG_YUV
slouken@70
   392
	fprintf(stderr, "Sending data to IPU..\n");
slouken@70
   393
#endif
slouken@70
   394
	packet.ptr = hwdata->ipu_imem;
slouken@70
   395
	packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8);
slouken@70
   396
	ioctl(hwdata->ipu_fd, PS2IOC_SENDA, &packet);
slouken@70
   397
slouken@70
   398
	/* Trigger the DMA to the IPU for conversion */
slouken@70
   399
#ifdef DEBUG_YUV
slouken@70
   400
	fprintf(stderr, "Trigging conversion command\n");
slouken@70
   401
#endif
slouken@70
   402
	cmd = (7 << 28) + hwdata->macroblocks;
slouken@70
   403
	if ( screen_image.psm == PS2_GS_PSMCT16 ) {
slouken@70
   404
		cmd += (1 << 27) +	/* Output RGB 555 */
slouken@70
   405
		       (1 << 26);	/* Dither output */
slouken@70
   406
	}
slouken@70
   407
	ioctl(hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd);
slouken@70
   408
slouken@70
   409
	/* Retrieve the converted image from the IPU */
slouken@70
   410
#ifdef DEBUG_YUV
slouken@70
   411
	fprintf(stderr, "Retrieving data from IPU..\n");
slouken@70
   412
#endif
slouken@70
   413
	packet.ptr = hwdata->ipu_omem;
slouken@70
   414
	packet.len = overlay->w * overlay->h *
slouken@70
   415
	             this->screen->format->BytesPerPixel;
slouken@70
   416
	ioctl(hwdata->ipu_fd, PS2IOC_RECV, &packet);
slouken@70
   417
slouken@70
   418
#ifdef DEBUG_YUV
slouken@70
   419
	fprintf(stderr, "Copying image to screen..\n");
slouken@70
   420
#endif
slouken@70
   421
	/* Wait for previous DMA to complete */
slouken@70
   422
	ioctl(console_fd, PS2IOC_SENDQCT, 1);
slouken@70
   423
slouken@70
   424
	/* Send the current image to the screen and scale it */
slouken@70
   425
	screen = this->screen;
slouken@1643
   426
	x = (unsigned int)dst->x;
slouken@1643
   427
	y = (unsigned int)dst->y;
slouken@70
   428
	if ( screen->offset ) {
slouken@70
   429
		x += (screen->offset % screen->pitch) /
slouken@70
   430
		     screen->format->BytesPerPixel;
slouken@70
   431
		y += (screen->offset / screen->pitch);
slouken@70
   432
	}
slouken@136
   433
	y += screen_image.y;
slouken@70
   434
	*hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
slouken@1643
   435
	x += (unsigned int)dst->w;
slouken@1643
   436
	y += (unsigned int)dst->h;
slouken@70
   437
	*hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16);
slouken@70
   438
	return ioctl(console_fd, PS2IOC_SENDL, &hwdata->plist);
slouken@70
   439
}
slouken@70
   440
slouken@70
   441
void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
slouken@70
   442
{
slouken@70
   443
	struct private_yuvhwdata *hwdata;
slouken@70
   444
slouken@70
   445
	hwdata = overlay->hwdata;
slouken@70
   446
	if ( hwdata ) {
slouken@70
   447
		if ( hwdata->ipu_fd >= 0 ) {
slouken@70
   448
			close(hwdata->ipu_fd);
slouken@70
   449
		}
slouken@70
   450
		if ( hwdata->dma_mem ) {
slouken@70
   451
			munmap(hwdata->dma_mem, hwdata->dma_len);
slouken@70
   452
		}
slouken@70
   453
		if ( hwdata->plist.packet ) {
slouken@1336
   454
			SDL_free(hwdata->plist.packet);
slouken@70
   455
		}
slouken@70
   456
		if ( hwdata->pixels ) {
slouken@1336
   457
			SDL_free(hwdata->pixels);
slouken@70
   458
		}
slouken@1336
   459
		SDL_free(hwdata);
slouken@70
   460
	}
slouken@70
   461
}