📄 osd.c
字号:
DRAMReadWord(card, card->OSD.odddata, 4, burst, 0); burst[1] = (burst[1] & 0x0FFF) | (trans << 12); DRAMWriteWord(card, card->OSD.odddata, 4, burst, 0); return 0;}// sets pixel <x>,<y> to color number <col>// returns 0 on success, 1 on errorint OSDSetPixel(struct cvdv_cards *card, int x, int y, int col){ u16 burst[4]; // minimal memory unit od DRAM u32 addr; int offset, ppw, pos, shift, height, posmask; u16 mask; if (!card->OSD.open) return -2; if ((y & 1) == card->OSD.evenfirst) { // even or odd frame? addr = card->OSD.oddbitmap; height = card->OSD.oddheight; } else { addr = card->OSD.evenbitmap; height = card->OSD.evenheight; } y >>= 1; if ((x >= 0) && (x < card->OSD.width) && (y >= 0) && (y < height)) { // clipping ppw = ((card->OSD.bpp == 4) ? 2 : ((card->OSD.bpp == 8) ? 1 : 3)); // OK, 4-(ln(bpp)/ln(2)) would have worked, too... pos = x + y * card->OSD.width; // pixel number in bitfield addr += (pos >> ppw); // 21 bit address of word with our pixel offset = addr & 3; // offset in burst addr &= ~3; // 21 bit burst address posmask = (1 << ppw) - 1; // mask for position inside word shift = ((posmask - (pos & posmask)) << (4 - ppw)); // pixel shift inside word mask = (1 << (1 << (4 - ppw))) - 1; // pixel mask DRAMReadWord(card, addr, 4, burst, 0); // get the burst with our pixel... burst[offset] = (burst[offset] & ~(mask << shift)) | ((col & mask) << shift); DRAMWriteWord(card, addr, 4, burst, 0); // ...and write it back return 0; } else return -1;}// returns color number of pixel <x>,<y>, or -1int OSDGetPixel(struct cvdv_cards *card, int x, int y){ u16 burst[4]; // minimal memory unit u32 addr; int offset, ppw, pos, shift, height, posmask; u16 mask; if (!card->OSD.open) return -2; if ((y & 1) == card->OSD.evenfirst) { // even or odd frame? addr = card->OSD.oddbitmap; height = card->OSD.oddheight; } else { addr = card->OSD.evenbitmap; height = card->OSD.evenheight; } y >>= 1; if ((x >= 0) && (x < card->OSD.width) && (y >= 0) && (y < height)) { // clipping ppw = ((card->OSD.bpp == 4) ? 2 : ((card->OSD.bpp == 8) ? 1 : 3)); // OK, 4-(ln(bpp)/ln(2)) would have worked, too... pos = x + y * card->OSD.width; // pixel number in bitfield addr += (pos >> ppw); // 21 bit address of word with our pixel offset = addr & 3; // offset in burst addr &= ~3; // 21 bit burst address posmask = (1 << ppw) - 1; // mask for position inside word shift = ((posmask - (pos & posmask)) << (4 - ppw)); // pixel shift inside word mask = (1 << (1 << (4 - ppw))) - 1; // pixel mask DRAMReadWord(card, addr, 4, burst, 0); // get the burst with our pixel... return (burst[offset] >> shift) & mask; // ...and return it's value } else return -1;}// fills pixels x0,y through x1,y with the content of data[]// returns 0 on success, -1 on clipping all pixelint OSDSetRow(struct cvdv_cards *card, int x0, int y, int x1, u8 * data){ u16 burst[4]; // minimal memory unit u32 addr, addr1, bitmap; int offset, offset1, ppw, pos, pos1, shift, shift0, shift1, shiftstep, height, bpp, x, i, endburst, endword; u16 mask, posmask; if (!card->OSD.open) return -2; if ((y & 1) == card->OSD.evenfirst) { bitmap = card->OSD.oddbitmap; height = card->OSD.oddheight; } else { bitmap = card->OSD.evenbitmap; height = card->OSD.evenheight; } y >>= 1; if ((y >= 0) && (y < height)) { i = 0; if (x0 > x1) { x = x1; x1 = x0; x0 = x; } if ((x0 >= card->OSD.width) || (x1 < 0)) return -1; if (x0 < 0) { i -= x0; x0 = 0; } if (x1 >= card->OSD.width) x1 = card->OSD.width - 1; bpp = card->OSD.bpp; // bits per pixel ppw = ((bpp == 4) ? 2 : ((bpp == 8) ? 1 : 3)); // positional parameter mask = (1 << bpp) - 1; // mask for one pixel posmask = (1 << ppw) - 1; // mask for position inside word pos = x0 + (y * card->OSD.width); // pixel number of first pixel pos1 = pos + x1 - x0; // pixel number of last pixel shift0 = ((posmask - (pos & posmask)) << (4 - ppw)); shift1 = ((posmask - (pos1 & posmask)) << (4 - ppw)); shiftstep = 1 << (4 - ppw); addr = bitmap + (pos >> ppw); // DRAM address of word with first pixel addr1 = bitmap + (pos1 >> ppw); // " " " " " last " offset = (int) (addr & 3); // word position inside burst offset1 = (int) (addr1 & 3); // number of last word in the last burst addr &= ~3; // burst address addr1 &= ~3; // burst address of last pixel endburst = (addr1 != addr); // end in other burst endword = (offset1 != offset); // end in other word // read old content of first burst if the row start after the beginning or // end before the end of the first burst if (offset || (pos & posmask) || (!endburst && ((offset1 != 3) || ((pos1 & posmask) != posmask)))) { DRAMReadWord(card, addr, 4, burst, 0); } // End beyond or at the end of this word? if (endburst || endword || ((pos1 & posmask) == posmask)) { // Fill first word for (shift = shift0; shift >= 0; shift -= shiftstep) { // bit position inside word burst[offset] = (burst[offset] & ~(mask << shift)) | ((data[i++] & mask) << shift); } if (endburst || endword) { // Any more words to fill? shift0 = posmask << (4 - ppw); // from here on, we start at the beginning of each word offset++; // fill the rest of the burst if (endburst) { // end not in this burst? while (offset <= 3) { // fill remaining words burst[offset] = 0x0000; // clear first for (shift = shift0; shift >= 0; shift -= shiftstep) { burst[offset] |= ((data [i++] & mask) << shift); } offset++; } DRAMWriteWord(card, addr, 4, burst, 0); // write first burst addr += 4; // go on to the next burst while (addr < addr1) { // all bursts between start and end burst for (offset = 0; offset <= 3; offset++) { // 4 words per burst burst[offset] = 0x0000; // clear first for (shift = shift0; shift >= 0; shift -= shiftstep) { burst [offset] |= ((data [i++] & mask) << shift); } } DRAMWriteWord(card, addr, 4, burst, 0); // write full burst addr += 4; // next burst } offset = 0; if ((offset1 < 3) || shift1) { // does the row ends before the end of the burst? DRAMReadWord(card, addr, 4, burst, 0); // then we have to read the old content } } while (offset < offset1) { // end not in this word burst[offset] = 0x0000; // clear first for (shift = shift0; shift >= 0; shift -= shiftstep) { burst[offset] |= ((data[i++] & mask) << shift); } offset++; } for (shift = shift0; shift >= shift1; shift -= shiftstep) { // last word burst[offset] = (burst[offset] & ~(mask << shift)) | ((data[i++] & mask) << shift); } } } else { // row starts and ends in one word for (shift = shift0; shift >= shift1; shift -= shiftstep) { // bit position inside word burst[offset] = (burst[offset] & ~(mask << shift)) | ((data[i++] & mask) << shift); } } DRAMWriteWord(card, addr, 4, burst, 0); // write only/last burst return 0; } else return -1;}// fills pixels x0,y0 through x1,y1 with the content of data[]// inc contains the width of one line in the data block,// inc<=0 uses blockwidth as linewidth// returns 0 on success, -1 on clipping all pixelint OSDSetBlock(struct cvdv_cards *card, int x0, int y0, int x1, int y1, int inc, u8 * data){ int i, w = x1 - x0 + 1, ret = 0; if (inc > 0) w = inc; for (i = y0; i <= y1; i++) { ret |= OSDSetRow(card, x0, i, x1, data); data += w; } return ret;}// fills pixels x0,y through x1,y with the color <col>// returns 0 on success, -1 on clipping all pixelint OSDFillRow(struct cvdv_cards *card, int x0, int y, int x1, int col){ u16 burst[4]; // minimal memory unit u32 addr, addr1, bitmap; int offset, offset1, ppw, pos, pos1, shift, shift0, shift1, shiftstep, height, bpp, x, i, endburst, endword; u16 mask, posmask; if (!card->OSD.open) return -2; if ((y & 1) == card->OSD.evenfirst) { bitmap = card->OSD.oddbitmap; height = card->OSD.oddheight; } else { bitmap = card->OSD.evenbitmap; height = card->OSD.evenheight; } y >>= 1; if ((y >= 0) && (y < height)) { i = 0; if (x0 > x1) { x = x1; x1 = x0; x0 = x; } if ((x0 >= card->OSD.width) || (x1 < 0)) return -1; if (x0 < 0) { i -= x0; x0 = 0; } if (x1 >= card->OSD.width) x1 = card->OSD.width - 1; bpp = card->OSD.bpp; // bits per pixel ppw = ((bpp == 4) ? 2 : ((bpp == 8) ? 1 : 3)); // positional parameter mask = (1 << bpp) - 1; // mask for one pixel posmask = (1 << ppw) - 1; // mask for position inside word pos = x0 + (y * card->OSD.width); // pixel number of first pixel pos1 = pos + x1 - x0; // pixel number of last pixel shift0 = ((posmask - (pos & posmask)) << (4 - ppw)); shift1 = ((posmask - (pos1 & posmask)) << (4 - ppw)); shiftstep = 1 << (4 - ppw); addr = bitmap + (pos >> ppw); // DRAM address of word with first pixel addr1 = bitmap + (pos1 >> ppw); // " " " " " last " offset = (int) (addr & 3); // word position inside burst offset1 = (int) (addr1 & 3); // number of last word in the last burst addr &= ~3; // burst address addr1 &= ~3; // burst address of last pixel endburst = (addr1 != addr); // end in other burst endword = (offset1 != offset); // end in other word // read old content of first burst if the row start after the beginning or // end before the end of the first burst if (offset || (pos & posmask) || (!endburst && ((offset1 != 3) || ((pos1 & posmask) != posmask)))) { DRAMReadWord(card, addr, 4, burst, 0); } if (endburst || endword || ((pos1 & posmask) == posmask)) { // end beyond or at the end of this word? for (shift = shift0; shift >= 0; shift -= shiftstep) { // bit position inside word burst[offset] = (burst[offset] & ~(mask << shift)) | ((col & mask) << shift); } if (endburst || endword) { shift0 = posmask << (4 - ppw); // from here on, we start at the beginning of each word offset++; // fill the rest of the burst if (endburst) { // end not in this burst? while (offset <= 3) { // fill remaining words burst[offset] = 0x0000; // clear first for (shift = shift0; shift >= 0; shift -= shiftstep) { burst[offset] |= ((col & mask) << shift); } offset++; } DRAMWriteWord(card, addr, 4, burst, 0); // write first burst addr += 4; // next burst while (addr < addr1) { // write all the bursts between start and end burst for (offset = 0; offset <= 3; offset++) { burst[offset] = 0x0000; for (shift = shift0; shift >= 0; shift -= shiftstep) { burst [offset] |= ((col & mask) << shift); } } DRAMWriteWord(card, addr, 4, burst, 0); addr += 4; } offset = 0; if ((offset1 < 3) || shift1) { // does the row ends before the end of the burst? DRAMReadWord(card, addr, 4, burst, 0); // then we have to read the old content } } while (offset < offset1) { // end not in this word burst[offset] = 0x0000; for (shift = shift0; shift >= 0; shift -= shiftstep) { burst[offset] |= ((col & mask) << shift); } offset++; } for (shift = shift0; shift >= shift1; shift -= shiftstep) { burst[offset] = (burst[offset] & ~(mask << shift)) | ((col & mask) << shift); } } } else { // row starts and ends in one word for (shift = shift0; shift >= shift1; shift -= shiftstep) { // bit position inside word burst[offset] = (burst[offset] & ~(mask << shift)) | ((col & mask) << shift); } } DRAMWriteWord(card, addr, 4, burst, 0); return 0; } else return -1;}// fills pixels x0,y0 through x1,y1 with the color <col>// returns 0 on success, -1 on clipping all pixelint OSDFillBlock(struct cvdv_cards *card, int x0, int y0, int x1, int y1, int col){ int i, ret = 0; for (i = y0; i <= y1; i++) ret |= OSDFillRow(card, x0, i, x1, col); return ret;}// draw a line from x0,y0 to x1,y1 with the color <col>int OSDLine(struct cvdv_cards *card, int x0, int y0, int x1, int y1, int col){ int ct, ix, iy, ax, ay, dx, dy, off;#define sgn(a) ((a)?(((a)>0)?1:-1):0) if (!card->OSD.open) return -2; dx = x1 - x0; dy = y1 - y0; if (dx == 0) { if (dy < 0) for (iy = y1; iy <= y0; iy++) OSDSetPixel(card, x0, iy, col); else for (iy = y0; iy <= y1; iy++) OSDSetPixel(card, x0, iy, col); } else if (dy == 0) { OSDFillRow(card, x0, y0, x1, col); } else { ay = 0; ax = 0; ix = sgn(dx); dx = abs(dx); iy = sgn(dy); dy = abs(dy); if (dx < dy) { off = dx; dx = dy; dy = off; ay = ix; ax = iy; ix = 0; iy = 0; } off = dx >> 1; ct = 1; OSDSetPixel(card, x0, y0, col); x1 = x0; y1 = y0; while (dx >= ct) { x0 += ix; y0 += ax; ct++; off += dy; if (off > dx) { off -= dx; x0 += ay; y0 += iy; } if (ax) { OSDSetPixel(card, x0, y0, col); } else { if (y0 != y1) { OSDFillRow(card, x1, y1, x0 - ay, col); x1 = x0; y1 = y0; } } } if (!ax) OSDFillRow(card, x1, y0, x0, col); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -