Annotation of margi2/osd.c, revision 1.2

1.1       cvs         1: /* 
                      2:     osd.c
                      3: 
                      4:     Copyright (C) Christian Wolff for convergence integrated media.
                      5: 
                      6:     This program is free software; you can redistribute it and/or modify
                      7:     it under the terms of the GNU General Public License as published by
                      8:     the Free Software Foundation; either version 2 of the License, or
                      9:     (at your option) any later version.
                     10: 
                     11:     This program is distributed in the hope that it will be useful,
                     12:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14:     GNU General Public License for more details.
                     15: 
                     16:     You should have received a copy of the GNU General Public License
                     17:     along with this program; if not, write to the Free Software
                     18:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     19: */
                     20: 
                     21:      ////////////////////////////////////////////////////////////////
                     22:     //                                                            //
                     23:    //  Functions to Draw on the On Screen Display of the L64021  //
                     24:   //  CLUT-Mode with 2, 4, or 8 bit per pixel, up to 720*576    //
                     25:  //                                                            //
                     26: ////////////////////////////////////////////////////////////////
                     27: // OSD Pixel Aspect Ratio:
                     28: // CCIR601 525 Lines (NTSC,PAL-M): 11/10 (100*100 appears as 100*110)
                     29: // CCIR601 625 Lines (PAL):        11/12 (100*100 appears as 100*91.6)
                     30: //
                     31: // OSD functions for external use:
                     32: //   int OSDOpen(struct cvdv_cards *card);
                     33: //   int OSDClose(struct cvdv_cards *card);
                     34: //   int OSDQuery(struct cvdv_cards *card, int *x0, int *y0, int *x1, int *y1, int *aspx, int *aspy);
                     35: //   int OSDStartPicture(struct cvdv_cards *card, int left, int top, int width, int height, int bit, int mix);
                     36: //   void OSDShow(struct cvdv_cards *card);
                     37: //   void OSDHide(struct cvdv_cards *card);
                     38: //   void OSDClear(struct cvdv_cards *card);
                     39: //   void OSDFill(struct cvdv_cards *card, int col);
                     40: //   int OSDSetColor(struct cvdv_cards *card, int num, int R, int G, int B, int mix, int trans);
                     41: //   int OSDSetPixel(struct cvdv_cards *card, int x, int y, int col);
                     42: //   int OSDGetPixel(struct cvdv_cards *card, int x, int y);
                     43: //   int OSDSetRow(struct cvdv_cards *card, int x0, int y, int x1, u8 *data);
                     44: //   int OSDFillRow(struct cvdv_cards *card, int x0, int y, int x1, int col);
                     45: //   void OSDLine(struct cvdv_cards *card, int x0, int y0, int x1, int y1, int col);
                     46: //
                     47: // Return codes: (unless otherwise specified)
                     48: //    0: OK
                     49: //   -1: Range error
                     50: //   -2: OSD not open
                     51: //
                     52: 
                     53: #define __NO_VERSION__
                     54: 
                     55: #include "osd.h"
                     56: #include "dram.h"
                     57: #include "l64021.h"
                     58: 
                     59:  // Builds a 4-word picture header in buf
                     60: // returns number of words in pixel field on success, -1 on error
                     61: int OSDHeader(u16 * buf,       // 4 words
                     62:              int *bit,         // bit per pixel: 2, 4, or 8
                     63:              int *startrow,    // position of our block, 
                     64:              int *stoprow,     // row: 0..313
                     65:              int *startcol,    // col: 0..864
                     66:              int *stopcol,     //
                     67:              int *mix,         // opacity for mixed pixel, 0..15 (0%..94% resp.)
                     68:              int nopal)
                     69: {                              // 1: use previous palette
                     70:        int count;
                     71:        if (buf != NULL) {
                     72:                if (*bit == 8)
                     73:                        *bit = 1;
                     74:                else if (*bit == 2)
                     75:                        *bit = 0;
                     76:                else
                     77:                        *bit = 2;
                     78:                if (*startrow < 0)
                     79:                        *startrow = 0;
                     80:                if (*startrow > 312)
                     81:                        *startrow = 312;
                     82:                if (*stoprow <= *startrow)
                     83:                        *stoprow = *startrow + 1;
                     84:                if (*stoprow > 313)
                     85:                        *stoprow = 313;
                     86:                if (*startcol < 0)
                     87:                        *startcol = 0;
                     88:                if (*startcol > 863)
                     89:                        *startcol = 863;
                     90:                if (*stopcol <= *startcol)
                     91:                        *stopcol = *startcol + 2;
                     92:                if (*stopcol > 864)
                     93:                        *stopcol = 864;
                     94:                if ((*stopcol - *startcol + 1) & 1)
                     95:                        (*stopcol)--;
                     96:                if (*mix < 0)
                     97:                        *mix = 0;
                     98:                if (*mix > 15)
                     99:                        *mix = 15;
                    100:                buf[0] = ((*bit << 14) & 0x8000) | (*startrow & 0x01FF);
                    101:                buf[1] =
                    102:                    ((*mix << 12) & 0xF000) | ((*bit << 11) & 0x0800) |
                    103:                    ((nopal) ? 0x0400 : 0x0000) | (*stoprow & 0x01FF);
                    104:                buf[2] = *startcol & 0x03FF;
                    105:                buf[3] = *stopcol & 0x03FF;
                    106:                count =
                    107:                    (*stoprow - *startrow + 1) * (*stopcol - *startcol +
                    108:                                                  1);
                    109:                if (*bit == 1) {
                    110:                        count =
                    111:                            ((count >> 3) + ((count & 0x07) ? 1 : 0)) << 2;
                    112:                        *bit = 8;
                    113:                } else if (*bit == 0) {
                    114:                        count =
                    115:                            ((count >> 5) + ((count & 0x1F) ? 1 : 0)) << 2;
                    116:                        *bit = 2;
                    117:                } else if (*bit == 2) {
                    118:                        count =
                    119:                            ((count >> 4) + ((count & 0x0F) ? 1 : 0)) << 2;
                    120:                        *bit = 4;
                    121:                }
                    122:                return count;   // word count of pixel data
                    123:        } else
                    124:                return -1;
                    125: }
                    126: 
                    127: // enables OSD mode
                    128: int OSDShow(struct cvdv_cards *card)
                    129: {
                    130:        if (card->OSD.open) {
                    131:                DecoderMaskByte(card, 0x109, 0x03, 0x01);
                    132:                DecoderDelByte(card, 0x112, 0x10);      // no filter
                    133:                return 0;
                    134:        } else
                    135:                return -2;
                    136: }
                    137: 
                    138: // disables OSD mode
                    139: int OSDHide(struct cvdv_cards *card)
                    140: {
                    141:        if (card->OSD.open) {
                    142:                DecoderMaskByte(card, 0x109, 0x03, 0x00);
                    143:                return 0;
                    144:        } else
                    145:                return -2;
                    146: }
                    147: 
                    148: // creates an empty picture in the memory of the card
                    149: // ONLY ONE PICTURE PER CARD!
                    150: // maximum sizes:     NTSC: 720*525  PAL: 720*576
                    151: // maximum positions: NTSC: 858*525  PAL: 864*625
                    152: // returns 0 on success, -1 on DRAM allocation error
                    153: int OSDStartPicture(struct cvdv_cards *card, int left, int top, int width,
                    154:                    int height, int bit, int mix)
                    155: {
                    156:        u16 TermHeader[] = { 0x01FF, 0x05FF, 0x0000, 0x0000 };
                    157:        u16 header[4];
                    158:        int size, pixelsize, palsize, frametop, startrow, stoprow,
                    159:            startcol, stopcol;
                    160: 
                    161:        if (card->OSD.open)
                    162:                return -2;
                    163:        if (top & 1) {
                    164:                card->OSD.evenfirst = 0;
                    165:                card->OSD.evenheight = height / 2;
                    166:                card->OSD.oddheight = height - card->OSD.evenheight;
                    167:        } else {
                    168:                card->OSD.evenfirst = 1;
                    169:                card->OSD.oddheight = height / 2;
                    170:                card->OSD.evenheight = height - card->OSD.oddheight;
                    171:        }
                    172: 
                    173:        // Setting the picture for the lines in the even field
                    174:        frametop = top / 2;
                    175:        startrow = frametop;
                    176:        stoprow = frametop + card->OSD.evenheight - 1;
                    177:        startcol = left;
                    178:        stopcol = left + width - 1;
                    179:        pixelsize =
                    180:            OSDHeader(header, &bit, &startrow, &stoprow, &startcol,
                    181:                      &stopcol, &mix, 0);
                    182:        card->OSD.evenheight = stoprow - startrow + 1;
                    183:        card->OSD.bpp = bit;
                    184:        if (bit == 8)
                    185:                palsize = 256;
                    186:        else if (bit == 2)
                    187:                palsize = 4;
                    188:        else
                    189:                palsize = 16;
                    190:        size = 8 + palsize + pixelsize;
                    191:        card->OSD.evenmem = DRAMAlloc(card, size, 32);
                    192:        if (card->OSD.evenmem == BLANK)
                    193:                return -1;
                    194:        card->OSD.evendata = card->OSD.evenmem;
                    195:        card->OSD.evenpalette = card->OSD.evendata + 4;
                    196:        card->OSD.evenbitmap = card->OSD.evenpalette + palsize;
                    197:        card->OSD.eventerm = card->OSD.evenbitmap + pixelsize;
                    198:        DecoderWriteWord(card, 0x110, (u16) (card->OSD.evendata >> 5));
                    199:        DRAMWriteWord(card, card->OSD.evendata, 4, header, 0);
                    200:        DRAMFillByte(card, card->OSD.evenpalette,
                    201:                     (palsize + pixelsize) * 2, 0x00);
                    202:        DRAMWriteWord(card, card->OSD.eventerm, 4, TermHeader, 0);
                    203: 
                    204:        // Setting the picture for the lines in the odd frame
                    205:        frametop += card->OSD.evenfirst;
                    206:        startrow = frametop;
                    207:        stoprow = frametop + card->OSD.oddheight - 1;
                    208:        pixelsize =
                    209:            OSDHeader(header, &bit, &startrow, &stoprow, &startcol,
                    210:                      &stopcol, &mix, 0);
                    211:        card->OSD.oddheight = stoprow - startrow + 1;
                    212:        size = 8 + palsize + pixelsize;
                    213:        card->OSD.oddmem = DRAMAlloc(card, size, 32);
                    214:        if (card->OSD.oddmem == BLANK)
                    215:                return -1;
                    216:        card->OSD.odddata = card->OSD.oddmem;
                    217:        card->OSD.oddpalette = card->OSD.odddata + 4;
                    218:        card->OSD.oddbitmap = card->OSD.oddpalette + palsize;
                    219:        card->OSD.oddterm = card->OSD.oddbitmap + pixelsize;
                    220:        DecoderWriteWord(card, 0x10E, (u16) (card->OSD.odddata >> 5));
                    221:        DRAMWriteWord(card, card->OSD.odddata, 4, header, 0);
                    222:        DRAMFillByte(card, card->OSD.oddpalette, (palsize + pixelsize) * 2,
                    223:                     0x00);
                    224:        DRAMWriteWord(card, card->OSD.oddterm, 4, TermHeader, 0);
                    225: 
                    226:        // Update of the picture dimensions  
                    227:        card->OSD.width = stopcol - startcol + 1;
                    228:        card->OSD.height = card->OSD.evenheight + card->OSD.oddheight;
                    229:        card->OSD.open = 1;
                    230: 
1.2     ! mocm      231:        MDEBUG(1,": OSD Open %dX%d, %d bit, mem 0x%08X/0x%08X\n",
1.1       cvs       232:               card->OSD.width, card->OSD.height, card->OSD.bpp,
                    233:               card->OSD.evendata, card->OSD.odddata);
                    234:        return 0;
                    235: }
                    236: 
                    237: // Disables OSD and releases the buffers
                    238: // returns 0 on success, 1 on "not open"
                    239: int OSDClose(struct cvdv_cards *card)
                    240: {
                    241:        if (card->OSD.open) {
                    242:                OSDHide(card);
                    243:                DRAMFree(card, card->OSD.evenmem);
                    244:                DRAMFree(card, card->OSD.oddmem);
                    245:                card->OSD.open = 0;
                    246:                return 0;
                    247:        } else
                    248:                return -2;
                    249: }
                    250: 
                    251: // Opens OSD with this size and bit depth
                    252: // returns 0 on success, 1 on DRAM allocation error, 2 on "already open"
                    253: int OSDOpen(struct cvdv_cards *card, int x0, int y0, int x1, int y1,
                    254:            int bit, int mix)
                    255: {
                    256:        int ret;
                    257:        if (card->OSD.open)
                    258:                OSDClose(card);
                    259:        if (bit < 0)
                    260:                bit = 8;
                    261:        else if (bit < 2)
                    262:                bit = 2;
                    263:        else if (bit < 4)
                    264:                bit = 4;
                    265:        else
                    266:                bit = 8;
                    267:        if (x0 < 0)
                    268:                x0 = 0;
                    269:        if (x1 < 0)
                    270:                x1 = 720 - 1;
                    271:        if (x1 < x0)
                    272:                x1 = x0;
                    273:        if (y0 < 0)
                    274:                y0 = 0;
                    275:        if (y1 < 0)
                    276:                y1 = 576 - 1;
                    277:        if (y1 < y0)
                    278:                y1 = y0;
                    279:        if ((x1 + 1) > 720)
                    280:                x1 = 720 - 1;
                    281:        if (x0 > x1)
                    282:                x0 = x1;
                    283:        if (CCIR601Lines(card->videomode) == 625) {     // PAL
                    284:                if ((y1 + 1) > 576)
                    285:                        y1 = 576 - 1;
                    286:                if (y0 > y1)
                    287:                        y0 = y1;
                    288:                if (!
                    289:                    (ret =
                    290:                     OSDStartPicture(card, 134 + x0, 48 + y0, x1 - x0 + 1,
                    291:                                     y1 - y0 + 1, bit, mix)))
                    292:                        card->OSD.aspectratio = 12;     // pixel aspect ratio 12/11
                    293:        } else {                // NTSC
                    294:                if ((y1 + 1) > 484)
                    295:                        y1 = 484 - 1;
                    296:                if (y0 > y1)
                    297:                        y0 = y1;
                    298:                if (!
                    299:                    (ret =
                    300:                     OSDStartPicture(card, 126 + x0, 44 + y0, x1 - x0 + 1,
                    301:                                     y1 - y0 + 1, bit, mix)))
                    302:                        card->OSD.aspectratio = 10;     // pixel aspect ratio 10/11
                    303:        }
                    304:        return ret;
                    305: }
                    306: 
                    307: // fills parameters with the picture dimensions and the pixel aspect ratio (aspy=11)
                    308: int OSDQuery(struct cvdv_cards *card, int *x0, int *y0, int *x1, int *y1,
                    309:             int *aspx)
                    310: {
                    311:        if (!card->OSD.open)
                    312:                return -2;
                    313:        *x0 = 0;
                    314:        *x1 = card->OSD.width - 1;
                    315:        *y0 = 0;
                    316:        *y1 = card->OSD.height - 1;
                    317:        *aspx = card->OSD.aspectratio;
                    318:        return 0;
                    319: }
                    320: 
                    321: // Sets all pixel to color 0
                    322: int OSDClear(struct cvdv_cards *card)
                    323: {
                    324:        if (!card->OSD.open)
                    325:                return -2;
                    326:        DRAMFillByte(card, card->OSD.oddbitmap,
                    327:                     (int) (card->OSD.oddterm - card->OSD.oddbitmap) * 2,
                    328:                     0x00);
                    329:        DRAMFillByte(card, card->OSD.evenbitmap,
                    330:                     (int) (card->OSD.eventerm - card->OSD.evenbitmap) * 2,
                    331:                     0x00);
                    332:        return 0;
                    333: }
                    334: 
                    335: // Sets all pixel to color <col>
                    336: int OSDFill(struct cvdv_cards *card, int col)
                    337: {
                    338:        u8 color;
                    339:        if (!card->OSD.open)
                    340:                return -2;
                    341:        if (card->OSD.bpp == 8) {
                    342:                color = col & 0xFF;
                    343:        } else if (card->OSD.bpp == 4) {
                    344:                color = (col & 0xF);
                    345:                color |= (color << 4);
                    346:        } else if (card->OSD.bpp == 2) {
                    347:                color = (col & 0x03);
                    348:                for (col = 1; col <= 3; col++)
                    349:                        color |= (color << 2);
                    350:        } else
                    351:                color = 0x00;
                    352:        DRAMFillByte(card, card->OSD.oddbitmap,
                    353:                     (int) (card->OSD.oddterm - card->OSD.oddbitmap) * 2,
                    354:                     color);
                    355:        DRAMFillByte(card, card->OSD.evenbitmap,
                    356:                     (int) (card->OSD.eventerm - card->OSD.evenbitmap) * 2,
                    357:                     color);
                    358:        return 0;
                    359: }
                    360: 
                    361: // converts RGB(8 bit) to YCrCb(OSD format)
                    362: // mix: 0=opacity 100% 1=opacity at mix value
                    363: // trans: 0=mix bit applies 1=opacity 0%
                    364: // returns word in OSD palette format
                    365: u16 OSDColor(u8 R, u8 G, u8 B, int mix, int trans)
                    366: {
                    367:        u16 Y, Cr, Cb;
                    368:        Y = R * 77 + G * 150 + B * 29;  // Luma=0.299R+0.587G+0.114B 0..65535
                    369:        Cb = 2048 + B * 8 - (Y >> 5);   // Cr 0..4095
                    370:        Cr = 2048 + R * 10 - (Y >> 5);  // Cb 0..4095
                    371:        return ((trans) ? 0 :   // transparent pixel
                    372:                (Y & 0xFC00) |  // Luma 0..63
                    373:                ((mix) ? 0x0100 : 0x0000) |     // Opacity applies
                    374:                ((Cb >> 4) & 0x00F0) |  // Cb 0..15
                    375:                ((Cr >> 8) & 0x000F)    // Cr 0..15
                    376:            );
                    377: }
                    378: 
                    379: // set palette entry <num> to <r,g,b>, <mix> and <trans> apply
                    380: // R,G,B: 0..255
                    381: // RGB=1: R=Red, G=Green, B=Blue  RGB=0: R=Y G=Cb B=Cr
                    382: // mix=0, trans=0: pixel opacity 100% (only OSD pixel shows)
                    383: // mix=1, trans=0: pixel opacity as specified in header
                    384: // trans=1: pixel opacity 0% (only video pixel shows)
                    385: // returns 0 on success, 1 on error
                    386: int OSDSetColor(struct cvdv_cards *card, int num, int R, int G, int B,
                    387:                int YUV, int mix, int trans)
                    388: {
                    389:        u16 burst[4];           // minimal memory unit
                    390:        u32 addr;
                    391:        u16 color;
                    392:        if (!card->OSD.open)
                    393:                return -2;
                    394:        if (R < 0)
                    395:                R = 0;
                    396:        if (R > 255)
                    397:                R = 255;
                    398:        if (G < 0)
                    399:                G = 0;
                    400:        if (G > 255)
                    401:                G = 255;
                    402:        if (B < 0)
                    403:                B = 0;
                    404:        if (B > 255)
                    405:                B = 255;
                    406:        if ((num >= 0) && (num < (1 << card->OSD.bpp))) {
1.2     ! mocm      407:                if (num==0) MDEBUG(4,"OSD SetColor num=%d, R=%d, G=%d, B=%d, YUV=%d, mix=%d, trans=%d\n",
        !           408:                                   num,R,G,B,YUV,mix,trans);
1.1       cvs       409:                color = ((YUV)
                    410:                         ? ((trans) ? 0 : ((R << 8) & 0xFC00) |
                    411:                            ((mix) ? 0x0100 : 0x0000) | (G & 0x00F0) |
                    412:                            ((B >> 4) & 0x000F)) : OSDColor(R, G, B, mix,
                    413:                                                            trans));
                    414: 
                    415:                addr = card->OSD.oddpalette + num;
                    416:                DRAMReadWord(card, addr & ~3, 4, burst, 0);
                    417:                burst[addr & 3] = color;
                    418:                DRAMWriteWord(card, addr & ~3, 4, burst, 0);
                    419: 
                    420:                addr = card->OSD.evenpalette + num;
                    421:                DRAMReadWord(card, addr & ~3, 4, burst, 0);
                    422:                burst[addr & 3] = color;
                    423:                DRAMWriteWord(card, addr & ~3, 4, burst, 0);
                    424: 
                    425:                return 0;
                    426:        } else
                    427:                return -1;
                    428: }
                    429: 
                    430: // Set a number of entries in the palette
                    431: // sets the entries "firstcolor" through "lastcolor" from the array "data"
                    432: // data has 4 byte for each color:
                    433: // R,G,B, and a transparency value: 0->tranparent, 1..254->mix, 255->no mix
                    434: int OSDSetPalette(struct cvdv_cards *card, int firstcolor, int lastcolor,
                    435:                  u8 * data)
                    436: {
                    437:        u16 burst[4];           // minimal memory unit
                    438:        u32 addr;
                    439:        u16 color;
                    440:        int num, i = 0;
                    441:        if (!card->OSD.open)
                    442:                return -2;
                    443:        for (num = firstcolor; num <= lastcolor; num++)
                    444:                if ((num >= 0) && (num < (1 << card->OSD.bpp))) {
                    445:                        color =
                    446:                            OSDColor(data[i], data[i + 1], data[i + 2],
                    447:                                     ((data[i + 3] < 255) ? 1 : 0),
                    448:                                     ((data[i + 3] == 0) ? 1 : 0));
                    449:                        i += 4;
                    450: 
                    451:                        addr = card->OSD.oddpalette + num;
                    452:                        DRAMReadWord(card, addr & ~3, 4, burst, 0);
                    453:                        burst[addr & 3] = color;
                    454:                        DRAMWriteWord(card, addr & ~3, 4, burst, 0);
                    455: 
                    456:                        addr = card->OSD.evenpalette + num;
                    457:                        DRAMReadWord(card, addr & ~3, 4, burst, 0);
                    458:                        burst[addr & 3] = color;
                    459:                        DRAMWriteWord(card, addr & ~3, 4, burst, 0);
                    460:                }
                    461:        return 0;
                    462: }
                    463: 
                    464: // Sets transparency of mixed pixel (0..15)
                    465: int OSDSetTrans(struct cvdv_cards *card, int trans)
                    466: {
                    467:        u16 burst[4];           // minimal memory unit
                    468:        if (!card->OSD.open)
                    469:                return -2;
                    470:        trans &= 0x000F;
                    471:        DRAMReadWord(card, card->OSD.evendata, 4, burst, 0);
                    472:        burst[1] = (burst[1] & 0x0FFF) | (trans << 12);
                    473:        DRAMWriteWord(card, card->OSD.evendata, 4, burst, 0);
                    474: 
                    475:        DRAMReadWord(card, card->OSD.odddata, 4, burst, 0);
                    476:        burst[1] = (burst[1] & 0x0FFF) | (trans << 12);
                    477:        DRAMWriteWord(card, card->OSD.odddata, 4, burst, 0);
                    478:        return 0;
                    479: }
                    480: 
                    481: // sets pixel <x>,<y> to color number <col>
                    482: // returns 0 on success, 1 on error
                    483: int OSDSetPixel(struct cvdv_cards *card, int x, int y, int col)
                    484: {
                    485:        u16 burst[4];           // minimal memory unit od DRAM
                    486:        u32 addr;
                    487:        int offset, ppw, pos, shift, height, posmask;
                    488:        u16 mask;
                    489: 
                    490:        if (!card->OSD.open)
                    491:                return -2;
                    492:        if ((y & 1) == card->OSD.evenfirst) {   // even or odd frame?
                    493:                addr = card->OSD.oddbitmap;
                    494:                height = card->OSD.oddheight;
                    495:        } else {
                    496:                addr = card->OSD.evenbitmap;
                    497:                height = card->OSD.evenheight;
                    498:        }
                    499:        y >>= 1;
                    500:        if ((x >= 0) && (x < card->OSD.width) && (y >= 0) && (y < height)) {    // clipping
                    501:                ppw =
                    502:                    ((card->OSD.bpp == 4) ? 2 : ((card->OSD.bpp == 8) ? 1 : 3));        // OK, 4-(ln(bpp)/ln(2)) would have worked, too...
                    503:                pos = x + y * card->OSD.width;  // pixel number in bitfield
                    504:                addr += (pos >> ppw);   // 21 bit address of word with our pixel
                    505:                offset = addr & 3;      // offset in burst
                    506:                addr &= ~3;     // 21 bit burst address
                    507:                posmask = (1 << ppw) - 1;       // mask for position inside word
                    508:                shift = ((posmask - (pos & posmask)) << (4 - ppw));     // pixel shift inside word
                    509:                mask = (1 << (1 << (4 - ppw))) - 1;     // pixel mask
                    510:                DRAMReadWord(card, addr, 4, burst, 0);  // get the burst with our pixel...
                    511:                burst[offset] =
                    512:                    (burst[offset] & ~(mask << shift)) | ((col & mask) <<
                    513:                                                          shift);
                    514:                DRAMWriteWord(card, addr, 4, burst, 0); // ...and write it back
                    515:                return 0;
                    516:        } else
                    517:                return -1;
                    518: }
                    519: 
                    520: // returns color number of pixel <x>,<y>,  or -1
                    521: int OSDGetPixel(struct cvdv_cards *card, int x, int y)
                    522: {
                    523:        u16 burst[4];           // minimal memory unit
                    524:        u32 addr;
                    525:        int offset, ppw, pos, shift, height, posmask;
                    526:        u16 mask;
                    527: 
                    528:        if (!card->OSD.open)
                    529:                return -2;
                    530:        if ((y & 1) == card->OSD.evenfirst) {   // even or odd frame?
                    531:                addr = card->OSD.oddbitmap;
                    532:                height = card->OSD.oddheight;
                    533:        } else {
                    534:                addr = card->OSD.evenbitmap;
                    535:                height = card->OSD.evenheight;
                    536:        }
                    537:        y >>= 1;
                    538:        if ((x >= 0) && (x < card->OSD.width) && (y >= 0) && (y < height)) {    // clipping
                    539:                ppw =
                    540:                    ((card->OSD.bpp == 4) ? 2 : ((card->OSD.bpp == 8) ? 1 : 3));        // OK, 4-(ln(bpp)/ln(2)) would have worked, too...
                    541:                pos = x + y * card->OSD.width;  // pixel number in bitfield
                    542:                addr += (pos >> ppw);   // 21 bit address of word with our pixel
                    543:                offset = addr & 3;      // offset in burst
                    544:                addr &= ~3;     // 21 bit burst address
                    545:                posmask = (1 << ppw) - 1;       // mask for position inside word
                    546:                shift = ((posmask - (pos & posmask)) << (4 - ppw));     // pixel shift inside word
                    547:                mask = (1 << (1 << (4 - ppw))) - 1;     // pixel mask
                    548:                DRAMReadWord(card, addr, 4, burst, 0);  // get the burst with our pixel...
                    549:                return (burst[offset] >> shift) & mask; // ...and return it's value 
                    550:        } else
                    551:                return -1;
                    552: }
                    553: 
                    554: // fills pixels x0,y through  x1,y with the content of data[]
                    555: // returns 0 on success, -1 on clipping all pixel
                    556: int OSDSetRow(struct cvdv_cards *card, int x0, int y, int x1, u8 * data)
                    557: {
                    558:        u16 burst[4];           // minimal memory unit
                    559:        u32 addr, addr1, bitmap;
                    560:        int offset, offset1, ppw, pos, pos1, shift, shift0, shift1,
                    561:            shiftstep, height, bpp, x, i, endburst, endword;
                    562:        u16 mask, posmask;
                    563: 
                    564:        if (!card->OSD.open)
                    565:                return -2;
                    566:        if ((y & 1) == card->OSD.evenfirst) {
                    567:                bitmap = card->OSD.oddbitmap;
                    568:                height = card->OSD.oddheight;
                    569:        } else {
                    570:                bitmap = card->OSD.evenbitmap;
                    571:                height = card->OSD.evenheight;
                    572:        }
                    573:        y >>= 1;
                    574:        if ((y >= 0) && (y < height)) {
                    575:                i = 0;
                    576:                if (x0 > x1) {
                    577:                        x = x1;
                    578:                        x1 = x0;
                    579:                        x0 = x;
                    580:                }
                    581:                if ((x0 >= card->OSD.width) || (x1 < 0))
                    582:                        return -1;
                    583:                if (x0 < 0) {
                    584:                        i -= x0;
                    585:                        x0 = 0;
                    586:                }
                    587:                if (x1 >= card->OSD.width)
                    588:                        x1 = card->OSD.width - 1;
                    589:                bpp = card->OSD.bpp;    // bits per pixel
                    590:                ppw = ((bpp == 4) ? 2 : ((bpp == 8) ? 1 : 3));  // positional parameter
                    591:                mask = (1 << bpp) - 1;  // mask for one pixel
                    592:                posmask = (1 << ppw) - 1;       // mask for position inside word
                    593: 
                    594:                pos = x0 + (y * card->OSD.width);       // pixel number of first pixel
                    595:                pos1 = pos + x1 - x0;   // pixel number of last pixel
                    596:                shift0 = ((posmask - (pos & posmask)) << (4 - ppw));
                    597:                shift1 = ((posmask - (pos1 & posmask)) << (4 - ppw));
                    598:                shiftstep = 1 << (4 - ppw);
                    599: 
                    600:                addr = bitmap + (pos >> ppw);   // DRAM address of word with first pixel
                    601:                addr1 = bitmap + (pos1 >> ppw); //  "      "    "    "   "   last    "
                    602:                offset = (int) (addr & 3);      // word position inside burst
                    603:                offset1 = (int) (addr1 & 3);    // number of last word in the last burst
                    604:                addr &= ~3;     // burst address
                    605:                addr1 &= ~3;    // burst address of last pixel
                    606: 
                    607:                endburst = (addr1 != addr);     // end in other burst
                    608:                endword = (offset1 != offset);  // end in other word
                    609: 
                    610:                // read old content of first burst if the row start after the beginning or 
                    611:                // end before the end of the first burst
                    612:                if (offset || (pos & posmask) ||
                    613:                    (!endburst
                    614:                     && ((offset1 != 3)
                    615:                         || ((pos1 & posmask) != posmask)))) {
                    616:                        DRAMReadWord(card, addr, 4, burst, 0);
                    617:                }
                    618:                // End beyond or at the end of this word?
                    619:                if (endburst || endword || ((pos1 & posmask) == posmask)) {
                    620:                        // Fill first word
                    621:                        for (shift = shift0; shift >= 0; shift -= shiftstep) {  // bit position inside word
                    622:                                burst[offset] =
                    623:                                    (burst[offset] & ~(mask << shift)) |
                    624:                                    ((data[i++] & mask) << shift);
                    625:                        }
                    626:                        if (endburst || endword) {      // Any more words to fill?
                    627:                                shift0 = posmask << (4 - ppw);  // from here on, we start at the beginning of each word
                    628:                                offset++;       // fill the rest of the burst
                    629:                                if (endburst) { // end not in this burst?
                    630:                                        while (offset <= 3) {   // fill remaining words
                    631:                                                burst[offset] = 0x0000; // clear first
                    632:                                                for (shift = shift0;
                    633:                                                     shift >= 0;
                    634:                                                     shift -= shiftstep) {
                    635:                                                        burst[offset] |=
                    636:                                                            ((data
                    637:                                                              [i++] & mask)
                    638:                                                             << shift);
                    639:                                                }
                    640:                                                offset++;
                    641:                                        }
                    642:                                        DRAMWriteWord(card, addr, 4, burst, 0); // write first burst
                    643:                                        addr += 4;      // go on to the next burst
                    644:                                        while (addr < addr1) {  // all bursts between start and end burst
                    645:                                                for (offset = 0;
                    646:                                                     offset <= 3; offset++) {   // 4 words per burst
                    647:                                                        burst[offset] = 0x0000; // clear first
                    648:                                                        for (shift =
                    649:                                                             shift0;
                    650:                                                             shift >= 0;
                    651:                                                             shift -=
                    652:                                                             shiftstep) {
                    653:                                                                burst
                    654:                                                                    [offset]
                    655:                                                                    |=
                    656:                                                                    ((data
                    657:                                                                      [i++]
                    658:                                                                      &
                    659:                                                                      mask)
                    660:                                                                     <<
                    661:                                                                     shift);
                    662:                                                        }
                    663:                                                }
                    664:                                                DRAMWriteWord(card, addr,
                    665:                                                              4, burst, 0);     // write full burst
                    666:                                                addr += 4;      // next burst
                    667:                                        }
                    668:                                        offset = 0;
                    669:                                        if ((offset1 < 3) || shift1) {  // does the row ends before the end of the burst?
                    670:                                                DRAMReadWord(card, addr, 4,
                    671:                                                             burst, 0); // then we have to read the old content
                    672:                                        }
                    673:                                }
                    674:                                while (offset < offset1) {      // end not in this word
                    675:                                        burst[offset] = 0x0000; // clear first
                    676:                                        for (shift = shift0; shift >= 0;
                    677:                                             shift -= shiftstep) {
                    678:                                                burst[offset] |=
                    679:                                                    ((data[i++] & mask) <<
                    680:                                                     shift);
                    681:                                        }
                    682:                                        offset++;
                    683:                                }
                    684:                                for (shift = shift0; shift >= shift1;
                    685:                                     shift -= shiftstep) {      // last word
                    686:                                        burst[offset] =
                    687:                                            (burst[offset] &
                    688:                                             ~(mask << shift)) |
                    689:                                            ((data[i++] & mask) << shift);
                    690:                                }
                    691:                        }
                    692:                } else {        // row starts and ends in one word
                    693:                        for (shift = shift0; shift >= shift1; shift -= shiftstep) {     // bit position inside word
                    694:                                burst[offset] =
                    695:                                    (burst[offset] & ~(mask << shift)) |
                    696:                                    ((data[i++] & mask) << shift);
                    697:                        }
                    698:                }
                    699:                DRAMWriteWord(card, addr, 4, burst, 0); // write only/last burst
                    700:                return 0;
                    701:        } else
                    702:                return -1;
                    703: }
                    704: 
                    705: // fills pixels x0,y0 through  x1,y1 with the content of data[]
                    706: // inc contains the width of one line in the data block,
                    707: // inc<=0 uses blockwidth as linewidth
                    708: // returns 0 on success, -1 on clipping all pixel
                    709: int OSDSetBlock(struct cvdv_cards *card, int x0, int y0, int x1, int y1,
                    710:                int inc, u8 * data)
                    711: {
                    712:        int i, w = x1 - x0 + 1, ret = 0;
                    713:        if (inc > 0)
                    714:                w = inc;
                    715:        for (i = y0; i <= y1; i++) {
                    716:                ret |= OSDSetRow(card, x0, i, x1, data);
                    717:                data += w;
                    718:        }
                    719:        return ret;
                    720: }
                    721: 
                    722: // fills pixels x0,y through  x1,y with the color <col>
                    723: // returns 0 on success, -1 on clipping all pixel
                    724: int OSDFillRow(struct cvdv_cards *card, int x0, int y, int x1, int col)
                    725: {
                    726:        u16 burst[4];           // minimal memory unit
                    727:        u32 addr, addr1, bitmap;
                    728:        int offset, offset1, ppw, pos, pos1, shift, shift0, shift1,
                    729:            shiftstep, height, bpp, x, i, endburst, endword;
                    730:        u16 mask, posmask;
                    731: 
                    732:        if (!card->OSD.open)
                    733:                return -2;
                    734:        if ((y & 1) == card->OSD.evenfirst) {
                    735:                bitmap = card->OSD.oddbitmap;
                    736:                height = card->OSD.oddheight;
                    737:        } else {
                    738:                bitmap = card->OSD.evenbitmap;
                    739:                height = card->OSD.evenheight;
                    740:        }
                    741:        y >>= 1;
                    742:        if ((y >= 0) && (y < height)) {
                    743:                i = 0;
                    744:                if (x0 > x1) {
                    745:                        x = x1;
                    746:                        x1 = x0;
                    747:                        x0 = x;
                    748:                }
                    749:                if ((x0 >= card->OSD.width) || (x1 < 0))
                    750:                        return -1;
                    751:                if (x0 < 0) {
                    752:                        i -= x0;
                    753:                        x0 = 0;
                    754:                }
                    755:                if (x1 >= card->OSD.width)
                    756:                        x1 = card->OSD.width - 1;
                    757:                bpp = card->OSD.bpp;    // bits per pixel
                    758:                ppw = ((bpp == 4) ? 2 : ((bpp == 8) ? 1 : 3));  // positional parameter
                    759:                mask = (1 << bpp) - 1;  // mask for one pixel
                    760:                posmask = (1 << ppw) - 1;       // mask for position inside word
                    761: 
                    762:                pos = x0 + (y * card->OSD.width);       // pixel number of first pixel
                    763:                pos1 = pos + x1 - x0;   // pixel number of last pixel
                    764:                shift0 = ((posmask - (pos & posmask)) << (4 - ppw));
                    765:                shift1 = ((posmask - (pos1 & posmask)) << (4 - ppw));
                    766:                shiftstep = 1 << (4 - ppw);
                    767: 
                    768:                addr = bitmap + (pos >> ppw);   // DRAM address of word with first pixel
                    769:                addr1 = bitmap + (pos1 >> ppw); //  "      "    "    "   "   last    "
                    770:                offset = (int) (addr & 3);      // word position inside burst
                    771:                offset1 = (int) (addr1 & 3);    // number of last word in the last burst
                    772:                addr &= ~3;     // burst address
                    773:                addr1 &= ~3;    // burst address of last pixel
                    774: 
                    775:                endburst = (addr1 != addr);     // end in other burst
                    776:                endword = (offset1 != offset);  // end in other word
                    777: 
                    778:                // read old content of first burst if the row start after the beginning or 
                    779:                // end before the end of the first burst
                    780:                if (offset || (pos & posmask) ||
                    781:                    (!endburst
                    782:                     && ((offset1 != 3)
                    783:                         || ((pos1 & posmask) != posmask)))) {
                    784:                        DRAMReadWord(card, addr, 4, burst, 0);
                    785:                }
                    786:                if (endburst || endword || ((pos1 & posmask) == posmask)) {     // end beyond or at the end of this word?
                    787:                        for (shift = shift0; shift >= 0; shift -= shiftstep) {  // bit position inside word
                    788:                                burst[offset] =
                    789:                                    (burst[offset] & ~(mask << shift)) |
                    790:                                    ((col & mask) << shift);
                    791:                        }
                    792:                        if (endburst || endword) {
                    793:                                shift0 = posmask << (4 - ppw);  // from here on, we start at the beginning of each word
                    794:                                offset++;       // fill the rest of the burst
                    795:                                if (endburst) { // end not in this burst?
                    796:                                        while (offset <= 3) {   // fill remaining words
                    797:                                                burst[offset] = 0x0000; // clear first
                    798:                                                for (shift = shift0;
                    799:                                                     shift >= 0;
                    800:                                                     shift -= shiftstep) {
                    801:                                                        burst[offset] |=
                    802:                                                            ((col & mask)
                    803:                                                             << shift);
                    804:                                                }
                    805:                                                offset++;
                    806:                                        }
                    807:                                        DRAMWriteWord(card, addr, 4, burst, 0); // write first burst
                    808:                                        addr += 4;      // next burst
                    809:                                        while (addr < addr1) {  // write all the bursts between start and end burst
                    810:                                                for (offset = 0;
                    811:                                                     offset <= 3; offset++) {
                    812:                                                        burst[offset] =
                    813:                                                            0x0000;
                    814:                                                        for (shift =
                    815:                                                             shift0;
                    816:                                                             shift >= 0;
                    817:                                                             shift -=
                    818:                                                             shiftstep) {
                    819:                                                                burst
                    820:                                                                    [offset]
                    821:                                                                    |=
                    822:                                                                    ((col
                    823:                                                                      &
                    824:                                                                      mask)
                    825:                                                                     <<
                    826:                                                                     shift);
                    827:                                                        }
                    828:                                                }
                    829:                                                DRAMWriteWord(card, addr,
                    830:                                                              4, burst, 0);
                    831:                                                addr += 4;
                    832:                                        }
                    833:                                        offset = 0;
                    834:                                        if ((offset1 < 3) || shift1) {  // does the row ends before the end of the burst?
                    835:                                                DRAMReadWord(card, addr, 4,
                    836:                                                             burst, 0); // then we have to read the old content
                    837:                                        }
                    838:                                }
                    839:                                while (offset < offset1) {      // end not in this word
                    840:                                        burst[offset] = 0x0000;
                    841:                                        for (shift = shift0; shift >= 0;
                    842:                                             shift -= shiftstep) {
                    843:                                                burst[offset] |=
                    844:                                                    ((col & mask) <<
                    845:                                                     shift);
                    846:                                        }
                    847:                                        offset++;
                    848:                                }
                    849:                                for (shift = shift0; shift >= shift1;
                    850:                                     shift -= shiftstep) {
                    851:                                        burst[offset] =
                    852:                                            (burst[offset] &
                    853:                                             ~(mask << shift)) | ((col &
                    854:                                                                   mask) <<
                    855:                                                                  shift);
                    856:                                }
                    857:                        }
                    858:                } else {        // row starts and ends in one word
                    859:                        for (shift = shift0; shift >= shift1; shift -= shiftstep) {     // bit position inside word
                    860:                                burst[offset] =
                    861:                                    (burst[offset] & ~(mask << shift)) |
                    862:                                    ((col & mask) << shift);
                    863:                        }
                    864:                }
                    865:                DRAMWriteWord(card, addr, 4, burst, 0);
                    866:                return 0;
                    867:        } else
                    868:                return -1;
                    869: }
                    870: 
                    871: // fills pixels x0,y0 through  x1,y1 with the color <col>
                    872: // returns 0 on success, -1 on clipping all pixel
                    873: int OSDFillBlock(struct cvdv_cards *card, int x0, int y0, int x1, int y1,
                    874:                 int col)
                    875: {
                    876:        int i, ret = 0;
                    877:        for (i = y0; i <= y1; i++)
                    878:                ret |= OSDFillRow(card, x0, i, x1, col);
                    879:        return ret;
                    880: }
                    881: 
                    882: // draw a line from x0,y0 to x1,y1 with the color <col>
                    883: int OSDLine(struct cvdv_cards *card, int x0, int y0, int x1, int y1,
                    884:            int col)
                    885: {
                    886:        int ct, ix, iy, ax, ay, dx, dy, off;
                    887: #define sgn(a) ((a)?(((a)>0)?1:-1):0)
                    888:        if (!card->OSD.open)
                    889:                return -2;
                    890:        dx = x1 - x0;
                    891:        dy = y1 - y0;
                    892:        if (dx == 0) {
                    893:                if (dy < 0)
                    894:                        for (iy = y1; iy <= y0; iy++)
                    895:                                OSDSetPixel(card, x0, iy, col);
                    896:                else
                    897:                        for (iy = y0; iy <= y1; iy++)
                    898:                                OSDSetPixel(card, x0, iy, col);
                    899:        } else if (dy == 0) {
                    900:                OSDFillRow(card, x0, y0, x1, col);
                    901:        } else {
                    902:                ay = 0;
                    903:                ax = 0;
                    904:                ix = sgn(dx);
                    905:                dx = abs(dx);
                    906:                iy = sgn(dy);
                    907:                dy = abs(dy);
                    908:                if (dx < dy) {
                    909:                        off = dx;
                    910:                        dx = dy;
                    911:                        dy = off;
                    912:                        ay = ix;
                    913:                        ax = iy;
                    914:                        ix = 0;
                    915:                        iy = 0;
                    916:                }
                    917:                off = dx >> 1;
                    918:                ct = 1;
                    919:                OSDSetPixel(card, x0, y0, col);
                    920:                x1 = x0;
                    921:                y1 = y0;
                    922:                while (dx >= ct) {
                    923:                        x0 += ix;
                    924:                        y0 += ax;
                    925:                        ct++;
                    926:                        off += dy;
                    927:                        if (off > dx) {
                    928:                                off -= dx;
                    929:                                x0 += ay;
                    930:                                y0 += iy;
                    931:                        }
                    932:                        if (ax) {
                    933:                                OSDSetPixel(card, x0, y0, col);
                    934:                        } else {
                    935:                                if (y0 != y1) {
                    936:                                        OSDFillRow(card, x1, y1, x0 - ay,
                    937:                                                   col);
                    938:                                        x1 = x0;
                    939:                                        y1 = y0;
                    940:                                }
                    941:                        }
                    942:                }
                    943:                if (!ax)
                    944:                        OSDFillRow(card, x1, y0, x0, col);
                    945:        }
                    946:        return 0;
                    947: }

LinuxTV legacy CVS <linuxtv.org/cvs>