Search
lxdream.org :: lxdream/src/pvr2/yuv.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/yuv.c
changeset 284:808617ee7135
prev282:01e53698ff38
next293:fe191b6381b5
author nkeynes
date Mon Jan 15 08:32:09 2007 +0000 (13 years ago)
permissions -rw-r--r--
last change Break vram routines out into pvr2mem.c
Initial (untested) implementation of stride textures
Hookup YUV converter code in pvr2.c
file annotate diff log raw
nkeynes@281
     1
/**
nkeynes@284
     2
 * $Id: yuv.c,v 1.3 2007-01-15 08:32:09 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@284
   104
	    pvr2_yuv_state.y = 0;
nkeynes@281
   105
	}
nkeynes@282
   106
    }
nkeynes@282
   107
    
nkeynes@282
   108
    MMIO_WRITE( PVR2, YUV_COUNT, MMIO_READ( PVR2, YUV_COUNT ) + 1 );
nkeynes@282
   109
}
nkeynes@282
   110
nkeynes@282
   111
/**
nkeynes@282
   112
 * Receive data from the SH4, usually via DMA. This method is mainly responsible
nkeynes@282
   113
 * for buffering the data into macroblock chunks and then passing it on to the
nkeynes@282
   114
 * real processing
nkeynes@282
   115
 */
nkeynes@282
   116
void pvr2_yuv_write( char *data, uint32_t length )
nkeynes@282
   117
{
nkeynes@282
   118
    int block_size = yuv_block_size[pvr2_yuv_state.input_format];
nkeynes@282
   119
nkeynes@282
   120
    if( pvr2_yuv_state.data_length != 0 ) { /* Append to existing data */
nkeynes@282
   121
	int tmp = MIN( length, block_size - pvr2_yuv_state.data_length );
nkeynes@282
   122
	memcpy( pvr2_yuv_state.data + pvr2_yuv_state.data_length, 
nkeynes@282
   123
		data, tmp );
nkeynes@282
   124
	pvr2_yuv_state.data_length += tmp;
nkeynes@282
   125
	data += tmp;
nkeynes@282
   126
	length -= tmp;
nkeynes@282
   127
	if( pvr2_yuv_state.data_length == block_size ) {
nkeynes@282
   128
	    pvr2_yuv_process_block( pvr2_yuv_state.data );
nkeynes@282
   129
	}
nkeynes@282
   130
    }
nkeynes@282
   131
nkeynes@282
   132
    while( length >= block_size ) {
nkeynes@282
   133
	pvr2_yuv_process_block( data );
nkeynes@282
   134
	data += block_size;
nkeynes@282
   135
	length -= block_size;
nkeynes@282
   136
    }
nkeynes@282
   137
	    
nkeynes@282
   138
    if( length != 0 ) { /* Save the left over data */
nkeynes@282
   139
	memcpy( pvr2_yuv_state.data, data, length );
nkeynes@282
   140
	pvr2_yuv_state.data_length = length;
nkeynes@281
   141
    }
nkeynes@281
   142
}
nkeynes@281
   143
nkeynes@284
   144
void pvr2_yuv_init( uint32_t target )
nkeynes@281
   145
{
nkeynes@282
   146
    pvr2_yuv_state.target = target;
nkeynes@282
   147
    pvr2_yuv_state.x = 0;
nkeynes@282
   148
    pvr2_yuv_state.y = 0;
nkeynes@282
   149
    pvr2_yuv_state.data_length = 0;
nkeynes@284
   150
    MMIO_WRITE( PVR2, YUV_COUNT, 0 );
nkeynes@284
   151
}
nkeynes@284
   152
nkeynes@284
   153
void pvr2_yuv_set_config( uint32_t config )
nkeynes@284
   154
{
nkeynes@284
   155
    pvr2_yuv_state.width = (config & 0x3f) + 1;
nkeynes@284
   156
    pvr2_yuv_state.height = ((config>>8) & 0x3f) +1;
nkeynes@284
   157
    pvr2_yuv_state.input_format = (config & 0x01000000) ? FORMAT_YUV422 : FORMAT_YUV420;
nkeynes@282
   158
    if( config & 0x00010000 ) {
nkeynes@282
   159
	pvr2_yuv_state.height *= pvr2_yuv_state.width;
nkeynes@282
   160
	pvr2_yuv_state.width = 1;
nkeynes@281
   161
    }
nkeynes@281
   162
}
.