src/video/ps2gs/SDL_gsyuv.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1659 14717b52abc0
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

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