📄 osd.c
字号:
/* osd.c Copyright (C) Christian Wolff for convergence integrated media. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/ //////////////////////////////////////////////////////////////// // // // Functions to Draw on the On Screen Display of the L64021 // // CLUT-Mode with 2, 4, or 8 bit per pixel, up to 720*576 // // //////////////////////////////////////////////////////////////////// OSD Pixel Aspect Ratio:// CCIR601 525 Lines (NTSC,PAL-M): 11/10 (100*100 appears as 100*110)// CCIR601 625 Lines (PAL): 11/12 (100*100 appears as 100*91.6)//// OSD functions for external use:// int OSDOpen(struct cvdv_cards *card);// int OSDClose(struct cvdv_cards *card);// int OSDQuery(struct cvdv_cards *card, int *x0, int *y0, int *x1, int *y1, int *aspx, int *aspy);// int OSDStartPicture(struct cvdv_cards *card, int left, int top, int width, int height, int bit, int mix);// void OSDShow(struct cvdv_cards *card);// void OSDHide(struct cvdv_cards *card);// void OSDClear(struct cvdv_cards *card);// void OSDFill(struct cvdv_cards *card, int col);// int OSDSetColor(struct cvdv_cards *card, int num, int R, int G, int B, int mix, int trans);// int OSDSetPixel(struct cvdv_cards *card, int x, int y, int col);// int OSDGetPixel(struct cvdv_cards *card, int x, int y);// int OSDSetRow(struct cvdv_cards *card, int x0, int y, int x1, u8 *data);// int OSDFillRow(struct cvdv_cards *card, int x0, int y, int x1, int col);// void OSDLine(struct cvdv_cards *card, int x0, int y0, int x1, int y1, int col);//// Return codes: (unless otherwise specified)// 0: OK// -1: Range error// -2: OSD not open//#define __NO_VERSION__#include "osd.h"#include "dram.h"#include "l64021.h" // Builds a 4-word picture header in buf// returns number of words in pixel field on success, -1 on errorint OSDHeader(u16 * buf, // 4 words int *bit, // bit per pixel: 2, 4, or 8 int *startrow, // position of our block, int *stoprow, // row: 0..313 int *startcol, // col: 0..864 int *stopcol, // int *mix, // opacity for mixed pixel, 0..15 (0%..94% resp.) int nopal){ // 1: use previous palette int count; if (buf != NULL) { if (*bit == 8) *bit = 1; else if (*bit == 2) *bit = 0; else *bit = 2; if (*startrow < 0) *startrow = 0; if (*startrow > 312) *startrow = 312; if (*stoprow <= *startrow) *stoprow = *startrow + 1; if (*stoprow > 313) *stoprow = 313; if (*startcol < 0) *startcol = 0; if (*startcol > 863) *startcol = 863; if (*stopcol <= *startcol) *stopcol = *startcol + 2; if (*stopcol > 864) *stopcol = 864; if ((*stopcol - *startcol + 1) & 1) (*stopcol)--; if (*mix < 0) *mix = 0; if (*mix > 15) *mix = 15; buf[0] = ((*bit << 14) & 0x8000) | (*startrow & 0x01FF); buf[1] = ((*mix << 12) & 0xF000) | ((*bit << 11) & 0x0800) | ((nopal) ? 0x0400 : 0x0000) | (*stoprow & 0x01FF); buf[2] = *startcol & 0x03FF; buf[3] = *stopcol & 0x03FF; count = (*stoprow - *startrow + 1) * (*stopcol - *startcol + 1); if (*bit == 1) { count = ((count >> 3) + ((count & 0x07) ? 1 : 0)) << 2; *bit = 8; } else if (*bit == 0) { count = ((count >> 5) + ((count & 0x1F) ? 1 : 0)) << 2; *bit = 2; } else if (*bit == 2) { count = ((count >> 4) + ((count & 0x0F) ? 1 : 0)) << 2; *bit = 4; } return count; // word count of pixel data } else return -1;}// enables OSD modeint OSDShow(struct cvdv_cards *card){ if (card->OSD.open) { DecoderMaskByte(card, 0x109, 0x03, 0x01); DecoderDelByte(card, 0x112, 0x10); // no filter return 0; } else return -2;}// disables OSD modeint OSDHide(struct cvdv_cards *card){ if (card->OSD.open) { DecoderMaskByte(card, 0x109, 0x03, 0x00); return 0; } else return -2;}// creates an empty picture in the memory of the card// ONLY ONE PICTURE PER CARD!// maximum sizes: NTSC: 720*525 PAL: 720*576// maximum positions: NTSC: 858*525 PAL: 864*625// returns 0 on success, -1 on DRAM allocation errorint OSDStartPicture(struct cvdv_cards *card, int left, int top, int width, int height, int bit, int mix){ u16 TermHeader[] = { 0x01FF, 0x05FF, 0x0000, 0x0000 }; u16 header[4]; int size, pixelsize, palsize, frametop, startrow, stoprow, startcol, stopcol; if (card->OSD.open) return -2; if (top & 1) { card->OSD.evenfirst = 0; card->OSD.evenheight = height / 2; card->OSD.oddheight = height - card->OSD.evenheight; } else { card->OSD.evenfirst = 1; card->OSD.oddheight = height / 2; card->OSD.evenheight = height - card->OSD.oddheight; } // Setting the picture for the lines in the even field frametop = top / 2; startrow = frametop; stoprow = frametop + card->OSD.evenheight - 1; startcol = left; stopcol = left + width - 1; pixelsize = OSDHeader(header, &bit, &startrow, &stoprow, &startcol, &stopcol, &mix, 0); card->OSD.evenheight = stoprow - startrow + 1; card->OSD.bpp = bit; if (bit == 8) palsize = 256; else if (bit == 2) palsize = 4; else palsize = 16; size = 8 + palsize + pixelsize; card->OSD.evenmem = DRAMAlloc(card, size, 32); if (card->OSD.evenmem == BLANK) return -1; card->OSD.evendata = card->OSD.evenmem; card->OSD.evenpalette = card->OSD.evendata + 4; card->OSD.evenbitmap = card->OSD.evenpalette + palsize; card->OSD.eventerm = card->OSD.evenbitmap + pixelsize; DecoderWriteWord(card, 0x110, (u16) (card->OSD.evendata >> 5)); DRAMWriteWord(card, card->OSD.evendata, 4, header, 0); DRAMFillByte(card, card->OSD.evenpalette, (palsize + pixelsize) * 2, 0x00); DRAMWriteWord(card, card->OSD.eventerm, 4, TermHeader, 0); // Setting the picture for the lines in the odd frame frametop += card->OSD.evenfirst; startrow = frametop; stoprow = frametop + card->OSD.oddheight - 1; pixelsize = OSDHeader(header, &bit, &startrow, &stoprow, &startcol, &stopcol, &mix, 0); card->OSD.oddheight = stoprow - startrow + 1; size = 8 + palsize + pixelsize; card->OSD.oddmem = DRAMAlloc(card, size, 32); if (card->OSD.oddmem == BLANK) return -1; card->OSD.odddata = card->OSD.oddmem; card->OSD.oddpalette = card->OSD.odddata + 4; card->OSD.oddbitmap = card->OSD.oddpalette + palsize; card->OSD.oddterm = card->OSD.oddbitmap + pixelsize; DecoderWriteWord(card, 0x10E, (u16) (card->OSD.odddata >> 5)); DRAMWriteWord(card, card->OSD.odddata, 4, header, 0); DRAMFillByte(card, card->OSD.oddpalette, (palsize + pixelsize) * 2, 0x00); DRAMWriteWord(card, card->OSD.oddterm, 4, TermHeader, 0); // Update of the picture dimensions card->OSD.width = stopcol - startcol + 1; card->OSD.height = card->OSD.evenheight + card->OSD.oddheight; card->OSD.open = 1; MDEBUG(1,": OSD Open %dX%d, %d bit, mem 0x%08X/0x%08X\n", card->OSD.width, card->OSD.height, card->OSD.bpp, card->OSD.evendata, card->OSD.odddata); return 0;}// Disables OSD and releases the buffers// returns 0 on success, 1 on "not open"int OSDClose(struct cvdv_cards *card){ if (card->OSD.open) { OSDHide(card); DRAMFree(card, card->OSD.evenmem); DRAMFree(card, card->OSD.oddmem); card->OSD.open = 0; return 0; } else return -2;}// Opens OSD with this size and bit depth// returns 0 on success, 1 on DRAM allocation error, 2 on "already open"int OSDOpen(struct cvdv_cards *card, int x0, int y0, int x1, int y1, int bit, int mix){ int ret; if (card->OSD.open) OSDClose(card); if (bit < 0) bit = 8; else if (bit < 2) bit = 2; else if (bit < 4) bit = 4; else bit = 8; if (x0 < 0) x0 = 0; if (x1 < 0) x1 = 720 - 1; if (x1 < x0) x1 = x0; if (y0 < 0) y0 = 0; if (y1 < 0) y1 = 576 - 1; if (y1 < y0) y1 = y0; if ((x1 + 1) > 720) x1 = 720 - 1; if (x0 > x1) x0 = x1; if (CCIR601Lines(card->videomode) == 625) { // PAL if ((y1 + 1) > 576) y1 = 576 - 1; if (y0 > y1) y0 = y1; if (! (ret = OSDStartPicture(card, 134 + x0, 48 + y0, x1 - x0 + 1, y1 - y0 + 1, bit, mix))) card->OSD.aspectratio = 12; // pixel aspect ratio 12/11 } else { // NTSC if ((y1 + 1) > 484) y1 = 484 - 1; if (y0 > y1) y0 = y1; if (! (ret = OSDStartPicture(card, 126 + x0, 44 + y0, x1 - x0 + 1, y1 - y0 + 1, bit, mix))) card->OSD.aspectratio = 10; // pixel aspect ratio 10/11 } return ret;}// fills parameters with the picture dimensions and the pixel aspect ratio (aspy=11)int OSDQuery(struct cvdv_cards *card, int *x0, int *y0, int *x1, int *y1, int *aspx){ if (!card->OSD.open) return -2; *x0 = 0; *x1 = card->OSD.width - 1; *y0 = 0; *y1 = card->OSD.height - 1; *aspx = card->OSD.aspectratio; return 0;}// Sets all pixel to color 0int OSDClear(struct cvdv_cards *card){ if (!card->OSD.open) return -2; DRAMFillByte(card, card->OSD.oddbitmap, (int) (card->OSD.oddterm - card->OSD.oddbitmap) * 2, 0x00); DRAMFillByte(card, card->OSD.evenbitmap, (int) (card->OSD.eventerm - card->OSD.evenbitmap) * 2, 0x00); return 0;}// Sets all pixel to color <col>int OSDFill(struct cvdv_cards *card, int col){ u8 color; if (!card->OSD.open) return -2; if (card->OSD.bpp == 8) { color = col & 0xFF; } else if (card->OSD.bpp == 4) { color = (col & 0xF); color |= (color << 4); } else if (card->OSD.bpp == 2) { color = (col & 0x03); for (col = 1; col <= 3; col++) color |= (color << 2); } else color = 0x00; DRAMFillByte(card, card->OSD.oddbitmap, (int) (card->OSD.oddterm - card->OSD.oddbitmap) * 2, color); DRAMFillByte(card, card->OSD.evenbitmap, (int) (card->OSD.eventerm - card->OSD.evenbitmap) * 2, color); return 0;}// converts RGB(8 bit) to YCrCb(OSD format)// mix: 0=opacity 100% 1=opacity at mix value// trans: 0=mix bit applies 1=opacity 0%// returns word in OSD palette formatu16 OSDColor(u8 R, u8 G, u8 B, int mix, int trans){ u16 Y, Cr, Cb; Y = R * 77 + G * 150 + B * 29; // Luma=0.299R+0.587G+0.114B 0..65535 Cb = 2048 + B * 8 - (Y >> 5); // Cr 0..4095 Cr = 2048 + R * 10 - (Y >> 5); // Cb 0..4095 return ((trans) ? 0 : // transparent pixel (Y & 0xFC00) | // Luma 0..63 ((mix) ? 0x0100 : 0x0000) | // Opacity applies ((Cb >> 4) & 0x00F0) | // Cb 0..15 ((Cr >> 8) & 0x000F) // Cr 0..15 );}// set palette entry <num> to <r,g,b>, <mix> and <trans> apply// R,G,B: 0..255// RGB=1: R=Red, G=Green, B=Blue RGB=0: R=Y G=Cb B=Cr// mix=0, trans=0: pixel opacity 100% (only OSD pixel shows)// mix=1, trans=0: pixel opacity as specified in header// trans=1: pixel opacity 0% (only video pixel shows)// returns 0 on success, 1 on errorint OSDSetColor(struct cvdv_cards *card, int num, int R, int G, int B, int YUV, int mix, int trans){ u16 burst[4]; // minimal memory unit u32 addr; u16 color; if (!card->OSD.open) return -2; if (R < 0) R = 0; if (R > 255) R = 255; if (G < 0) G = 0; if (G > 255) G = 255; if (B < 0) B = 0; if (B > 255) B = 255; if ((num >= 0) && (num < (1 << card->OSD.bpp))) { if (num==0) MDEBUG(4,"OSD SetColor num=%d, R=%d, G=%d, B=%d, YUV=%d, mix=%d, trans=%d\n", num,R,G,B,YUV,mix,trans); color = ((YUV) ? ((trans) ? 0 : ((R << 8) & 0xFC00) | ((mix) ? 0x0100 : 0x0000) | (G & 0x00F0) | ((B >> 4) & 0x000F)) : OSDColor(R, G, B, mix, trans)); addr = card->OSD.oddpalette + num; DRAMReadWord(card, addr & ~3, 4, burst, 0); burst[addr & 3] = color; DRAMWriteWord(card, addr & ~3, 4, burst, 0); addr = card->OSD.evenpalette + num; DRAMReadWord(card, addr & ~3, 4, burst, 0); burst[addr & 3] = color; DRAMWriteWord(card, addr & ~3, 4, burst, 0); return 0; } else return -1;}// Set a number of entries in the palette// sets the entries "firstcolor" through "lastcolor" from the array "data"// data has 4 byte for each color:// R,G,B, and a transparency value: 0->tranparent, 1..254->mix, 255->no mixint OSDSetPalette(struct cvdv_cards *card, int firstcolor, int lastcolor, u8 * data){ u16 burst[4]; // minimal memory unit u32 addr; u16 color; int num, i = 0; if (!card->OSD.open) return -2; for (num = firstcolor; num <= lastcolor; num++) if ((num >= 0) && (num < (1 << card->OSD.bpp))) { color = OSDColor(data[i], data[i + 1], data[i + 2], ((data[i + 3] < 255) ? 1 : 0), ((data[i + 3] == 0) ? 1 : 0)); i += 4; addr = card->OSD.oddpalette + num; DRAMReadWord(card, addr & ~3, 4, burst, 0); burst[addr & 3] = color; DRAMWriteWord(card, addr & ~3, 4, burst, 0); addr = card->OSD.evenpalette + num; DRAMReadWord(card, addr & ~3, 4, burst, 0); burst[addr & 3] = color; DRAMWriteWord(card, addr & ~3, 4, burst, 0); } return 0;}// Sets transparency of mixed pixel (0..15)int OSDSetTrans(struct cvdv_cards *card, int trans){ u16 burst[4]; // minimal memory unit if (!card->OSD.open) return -2; trans &= 0x000F; DRAMReadWord(card, card->OSD.evendata, 4, burst, 0); burst[1] = (burst[1] & 0x0FFF) | (trans << 12); DRAMWriteWord(card, card->OSD.evendata, 4, burst, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -