Search
lxdream.org :: lxdream/src/pvr2/yuv.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/yuv.c
changeset 282:01e53698ff38
prev281:2019e605cb27
next284:808617ee7135
author nkeynes
date Mon Jan 15 08:30:50 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Commit testyuv WIP
file annotate diff log raw
nkeynes@281
     1
/**
nkeynes@282
     2
 * $Id: yuv.c,v 1.2 2007-01-14 11:43:00 nkeynes Exp $
nkeynes@281
     3
 *
nkeynes@281
     4
 * YUV420 and YUV422 decoding
nkeynes@281
     5
 *
nkeynes@281
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@281
     7
 *
nkeynes@281
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@281
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@281
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@281
    11
 * (at your option) any later version.
nkeynes@281
    12
 *
nkeynes@281
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@281
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@281
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@281
    16
 * GNU General Public License for more details.
nkeynes@281
    17
 */
nkeynes@281
    18
#include "dream.h"
nkeynes@282
    19
#include "asic.h"
nkeynes@282
    20
#include "pvr2/pvr2.h"
nkeynes@281
    21
nkeynes@281
    22
#define YUV420_BLOCK_SIZE 384
nkeynes@282
    23
#define YUV422_BLOCK_SIZE 512
nkeynes@281
    24
nkeynes@282
    25
#define FORMAT_YUV420 0
nkeynes@282
    26
#define FORMAT_YUV422 1
nkeynes@282
    27
nkeynes@282
    28
nkeynes@282
    29
static int yuv_block_size[2] = { YUV420_BLOCK_SIZE, YUV422_BLOCK_SIZE };
nkeynes@282
    30
nkeynes@282
    31
struct yuv_state {
nkeynes@282
    32
    uint32_t target;
nkeynes@282
    33
    int width;
nkeynes@282
    34
    int height;
nkeynes@282
    35
    int input_format;
nkeynes@282
    36
    char data[512];
nkeynes@282
    37
    int data_length;
nkeynes@282
    38
    int x, y;
nkeynes@282
    39
} pvr2_yuv_state;
nkeynes@282
    40
nkeynes@282
    41
/**
nkeynes@282
    42
 * Transformation table for yuv420.
nkeynes@282
    43
 */
nkeynes@282
    44
uint16_t yuv420_lut[512] = { 0, 128, 64, 129, 1, 130, 65, 131, 2, 132, 66, 133, 3, 134, 67, 135, 4, 192, 68, 193, 5, 194, 69, 195, 6, 196, 70, 197, 7, 198, 71, 199,
nkeynes@282
    45
			 0, 136, 64, 137, 1, 138, 65, 139, 2, 140, 66, 141, 3, 142, 67, 143, 4, 200, 68, 201, 5, 202, 69, 203, 6, 204, 70, 205, 7, 206, 71, 207,
nkeynes@282
    46
			 8, 144, 72, 145, 9, 146, 73, 147, 10, 148, 74, 149, 11, 150, 75, 151, 12, 208, 76, 209, 13, 210, 77, 211, 14, 212, 78, 213, 15, 214, 79, 215,
nkeynes@282
    47
			 8, 152, 72, 153, 9, 154, 73, 155, 10, 156, 74, 157, 11, 158, 75, 159, 12, 216, 76, 217, 13, 218, 77, 219, 14, 220, 78, 221, 15, 222, 79, 223,
nkeynes@282
    48
			 16, 160, 80, 161, 17, 162, 81, 163, 18, 164, 82, 165, 19, 166, 83, 167, 20, 224, 84, 225, 21, 226, 85, 227, 22, 228, 86, 229, 23, 230, 87, 231,
nkeynes@282
    49
			 16, 168, 80, 169, 17, 170, 81, 171, 18, 172, 82, 173, 19, 174, 83, 175, 20, 232, 84, 233, 21, 234, 85, 235, 22, 236, 86, 237, 23, 238, 87, 239,
nkeynes@282
    50
			 24, 176, 88, 177, 25, 178, 89, 179, 26, 180, 90, 181, 27, 182, 91, 183, 28, 240, 92, 241, 29, 242, 93, 243, 30, 244, 94, 245, 31, 246, 95, 247,
nkeynes@282
    51
			 24, 184, 88, 185, 25, 186, 89, 187, 26, 188, 90, 189, 27, 190, 91, 191, 28, 248, 92, 249, 29, 250, 93, 251, 30, 252, 94, 253, 31, 254, 95, 255,
nkeynes@282
    52
			 32, 256, 96, 257, 33, 258, 97, 259, 34, 260, 98, 261, 35, 262, 99, 263, 36, 320, 100, 321, 37, 322, 101, 323, 38, 324, 102, 325, 39, 326, 103, 327,
nkeynes@282
    53
			 32, 264, 96, 265, 33, 266, 97, 267, 34, 268, 98, 269, 35, 270, 99, 271, 36, 328, 100, 329, 37, 330, 101, 331, 38, 332, 102, 333, 39, 334, 103, 335,
nkeynes@282
    54
			 40, 272, 104, 273, 41, 274, 105, 275, 42, 276, 106, 277, 43, 278, 107, 279, 44, 336, 108, 337, 45, 338, 109, 339, 46, 340, 110, 341, 47, 342, 111, 343,
nkeynes@282
    55
			 40, 280, 104, 281, 41, 282, 105, 283, 42, 284, 106, 285, 43, 286, 107, 287, 44, 344, 108, 345, 45, 346, 109, 347, 46, 348, 110, 349, 47, 350, 111, 351,
nkeynes@282
    56
			 48, 288, 112, 289, 49, 290, 113, 291, 50, 292, 114, 293, 51, 294, 115, 295, 52, 352, 116, 353, 53, 354, 117, 355, 54, 356, 118, 357, 55, 358, 119, 359,
nkeynes@282
    57
			 48, 296, 112, 297, 49, 298, 113, 299, 50, 300, 114, 301, 51, 302, 115, 303, 52, 360, 116, 361, 53, 362, 117, 363, 54, 364, 118, 365, 55, 366, 119, 367,
nkeynes@282
    58
			 56, 304, 120, 305, 57, 306, 121, 307, 58, 308, 122, 309, 59, 310, 123, 311, 60, 368, 124, 369, 61, 370, 125, 371, 62, 372, 126, 373, 63, 374, 127, 375,
nkeynes@282
    59
			 56, 312, 120, 313, 57, 314, 121, 315, 58, 316, 122, 317, 59, 318, 123, 319, 60, 376, 124, 377, 61, 378, 125, 379, 62, 380, 126, 381, 63, 382, 127, 383 };
nkeynes@282
    60
nkeynes@282
    61
nkeynes@282
    62
/**
nkeynes@282
    63
 * Input is 8x8 U, 8x8 V, 8x8 Y00, 8x8 Y01, 8x8 Y10, 8x8 Y11, 8 bits each,
nkeynes@282
    64
 * for a total of 384 bytes.
nkeynes@282
    65
 * Output is UVYV = 32 bits = 2 horizontal pixels, 8x16 = 512 bytes
nkeynes@282
    66
 */
nkeynes@282
    67
void pvr2_decode_yuv420( char *dest, char *src )
nkeynes@281
    68
{
nkeynes@282
    69
    int i;
nkeynes@282
    70
    for( i=0; i<512; i++ ) {
nkeynes@282
    71
	dest[i] = src[yuv420_lut[i]];
nkeynes@282
    72
    }
nkeynes@282
    73
}
nkeynes@282
    74
nkeynes@282
    75
void pvr2_decode_yuv422( char *dest, char *src )
nkeynes@282
    76
{
nkeynes@281
    77
nkeynes@281
    78
}
nkeynes@281
    79
nkeynes@281
    80
/**
nkeynes@282
    81
 * Process a single macroblock of YUV data and write it out to 
nkeynes@282
    82
 * texture vram.
nkeynes@281
    83
 */
nkeynes@282
    84
void pvr2_yuv_process_block( char *data )
nkeynes@281
    85
{
nkeynes@282
    86
    char output[512];
nkeynes@282
    87
nkeynes@282
    88
    if( pvr2_yuv_state.input_format == FORMAT_YUV420 ) {
nkeynes@282
    89
	pvr2_decode_yuv420( output, data );
nkeynes@282
    90
    } else {
nkeynes@282
    91
	pvr2_decode_yuv422( output, data );
nkeynes@282
    92
    }
nkeynes@281
    93
    
nkeynes@282
    94
    uint32_t target = pvr2_yuv_state.target + 
nkeynes@282
    95
	(pvr2_yuv_state.y * pvr2_yuv_state.width * 512) +
nkeynes@282
    96
	(pvr2_yuv_state.x * 32);
nkeynes@282
    97
nkeynes@282
    98
    pvr2_vram64_write_stride( target, output, 32, pvr2_yuv_state.width*32, 16 );
nkeynes@282
    99
    if( ++pvr2_yuv_state.x >= pvr2_yuv_state.width ) {
nkeynes@282
   100
	pvr2_yuv_state.x = 0;
nkeynes@282
   101
	pvr2_yuv_state.y++;
nkeynes@282
   102
	if( pvr2_yuv_state.y >= pvr2_yuv_state.height ) {
nkeynes@282
   103
	    asic_event( EVENT_PVR_YUV_DONE );
nkeynes@281
   104
	}
nkeynes@282
   105
    }
nkeynes@282
   106
    
nkeynes@282
   107
    MMIO_WRITE( PVR2, YUV_COUNT, MMIO_READ( PVR2, YUV_COUNT ) + 1 );
nkeynes@282
   108
}
nkeynes@282
   109
nkeynes@282
   110
/**
nkeynes@282
   111
 * Receive data from the SH4, usually via DMA. This method is mainly responsible
nkeynes@282
   112
 * for buffering the data into macroblock chunks and then passing it on to the
nkeynes@282
   113
 * real processing
nkeynes@282
   114
 */
nkeynes@282
   115
void pvr2_yuv_write( char *data, uint32_t length )
nkeynes@282
   116
{
nkeynes@282
   117
    int block_size = yuv_block_size[pvr2_yuv_state.input_format];
nkeynes@282
   118
nkeynes@282
   119
    if( pvr2_yuv_state.data_length != 0 ) { /* Append to existing data */
nkeynes@282
   120
	int tmp = MIN( length, block_size - pvr2_yuv_state.data_length );
nkeynes@282
   121
	memcpy( pvr2_yuv_state.data + pvr2_yuv_state.data_length, 
nkeynes@282
   122
		data, tmp );
nkeynes@282
   123
	pvr2_yuv_state.data_length += tmp;
nkeynes@282
   124
	data += tmp;
nkeynes@282
   125
	length -= tmp;
nkeynes@282
   126
	if( pvr2_yuv_state.data_length == block_size ) {
nkeynes@282
   127
	    pvr2_yuv_process_block( pvr2_yuv_state.data );
nkeynes@282
   128
	}
nkeynes@282
   129
    }
nkeynes@282
   130
nkeynes@282
   131
    while( length >= block_size ) {
nkeynes@282
   132
	pvr2_yuv_process_block( data );
nkeynes@282
   133
	data += block_size;
nkeynes@282
   134
	length -= block_size;
nkeynes@282
   135
    }
nkeynes@282
   136
	    
nkeynes@282
   137
    if( length != 0 ) { /* Save the left over data */
nkeynes@282
   138
	memcpy( pvr2_yuv_state.data, data, length );
nkeynes@282
   139
	pvr2_yuv_state.data_length = length;
nkeynes@281
   140
    }
nkeynes@281
   141
}
nkeynes@281
   142
nkeynes@282
   143
void pvr2_yuv_init( uint32_t target, uint32_t config )
nkeynes@281
   144
{
nkeynes@282
   145
    pvr2_yuv_state.target = target;
nkeynes@282
   146
    pvr2_yuv_state.width = (config & 0x3f) + 1;
nkeynes@282
   147
    pvr2_yuv_state.height = ((config>>8) & 0x3f) +1;
nkeynes@282
   148
    pvr2_yuv_state.x = 0;
nkeynes@282
   149
    pvr2_yuv_state.y = 0;
nkeynes@282
   150
    pvr2_yuv_state.data_length = 0;
nkeynes@282
   151
    pvr2_yuv_state.input_format = (config & 0x01000000) ? FORMAT_YUV420 : FORMAT_YUV422;
nkeynes@282
   152
    if( config & 0x00010000 ) {
nkeynes@282
   153
	pvr2_yuv_state.height *= pvr2_yuv_state.width;
nkeynes@282
   154
	pvr2_yuv_state.width = 1;
nkeynes@281
   155
    }
nkeynes@282
   156
    MMIO_WRITE( PVR2, YUV_COUNT, 0 );
nkeynes@281
   157
}
.