src/video/ps2gs/SDL_gsyuv.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 08:11:06 +0000
changeset 3565 f43c8f688f77
parent 2859 99210400e8b9
child 3626 596468a8459e
permissions -rw-r--r--
Fixed bug #906

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