diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c index 3ce2c75b31906b01d1824d509021581a4283a7f3..a1a47f5bdc3e6fdbdbb662844f6fbbc028695dd7 100644 --- a/src/conio/bitmap_con.c +++ b/src/conio/bitmap_con.c @@ -64,7 +64,7 @@ static int dbg_pthread_mutex_trylock(pthread_mutex_t *lptr, unsigned line) /* Structs */ struct bitmap_screen { - uint32_t *screen; + //uint32_t *screen; int screenwidth; int screenheight; pthread_mutex_t screenlock; @@ -277,12 +277,14 @@ static int bitmap_vmem_puttext_locked(int sx, int sy, int ex, int ey, struct vme pthread_mutex_lock(&vstatlock); vmem_ptr = get_vmem(&vstat); + pthread_mutex_unlock(&vstatlock); for(y=sy-1;y<ey;y++) { for(x=sx-1;x<ex;x++) { memcpy(&vmem_ptr->vmem[y*cio_textinfo.screenwidth+x], fill++, sizeof(*fill)); bitmap_draw_one_char(x+1, y+1); } } + pthread_mutex_lock(&vstatlock); release_vmem(vmem_ptr); pthread_mutex_unlock(&vstatlock); return(1); @@ -356,6 +358,12 @@ static void cb_drawrect(struct rectlist *data) int x, y; uint32_t *pixel; uint32_t cv; + int curs_start; + int curs_end; + int curs_row; + int curs_col; + int charheight; + int charwidth; if (data == NULL) return; @@ -370,16 +378,22 @@ static void cb_drawrect(struct rectlist *data) * 5) When blinking, the cursor is shown when vstat.blink is true. */ pthread_mutex_lock(&vstatlock); + curs_start = vstat.curs_start; + curs_end = vstat.curs_end; + curs_row = vstat.curs_row; + curs_col = vstat.curs_col; + charheight = vstat.charheight; + charwidth = vstat.charwidth; + pthread_mutex_unlock(&vstatlock); if (cursor_visible_locked()) { cv = color_value(ciolib_fg); - for (y = vstat.curs_start; y <= vstat.curs_end; y++) { - pixel = &data->data[((vstat.curs_row - 1) * vstat.charheight + y) * data->rect.width + (vstat.curs_col - 1) * vstat.charwidth]; - for (x = 0; x < vstat.charwidth; x++) { + for (y = curs_start; y <= curs_end; y++) { + pixel = &data->data[((curs_row - 1) * charheight + y) * data->rect.width + (curs_col - 1) * charwidth]; + for (x = 0; x < charwidth; x++) { *(pixel++) = cv; } } } - pthread_mutex_unlock(&vstatlock); pthread_mutex_lock(&callbacks.lock); callbacks.drawrect(data); callbacks.rects++; @@ -449,13 +463,16 @@ static uint32_t color_value(uint32_t col) static struct rectlist *get_full_rectangle_locked(struct bitmap_screen *screen) { struct rectlist *rect; + size_t sz = screen->screenwidth * screen->screenheight; + size_t pos; // TODO: Some sort of caching here would make things faster...? if(callbacks.drawrect) { rect = alloc_full_rect(screen); if (!rect) return rect; - memcpy(rect->data, screen->rect->data, sizeof(*rect->data) * screen->screenwidth * screen->screenheight); + for (pos = 0; pos < sz; pos++) + rect->data[pos] = color_value(screen->rect->data[pos]); return rect; } return NULL; @@ -544,7 +561,7 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos) return(-1); } - if((!screena.screen) || (!screenb.screen)) { + if((!screena.rect) || (!screenb.rect)) { pthread_mutex_unlock(&screenb.screenlock); pthread_mutex_unlock(&screena.screenlock); return(-1); @@ -575,32 +592,28 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos) } if(fb & (0x80 >> (fdx & 7)) && draw_fg) { - if (screena.screen[pixeloffset] != fg) { + if (screena.rect->data[pixeloffset] != fg) { screena.update_pixels = 1; - screena.screen[pixeloffset] = fg; - screena.rect->data[pixeloffset] = color_value(fg); + screena.rect->data[pixeloffset] = fg; } } else { - if (screena.screen[pixeloffset] != bg) { + if (screena.rect->data[pixeloffset] != bg) { screena.update_pixels = 1; - screena.screen[pixeloffset] = bg; - screena.rect->data[pixeloffset] = color_value(bg); + screena.rect->data[pixeloffset] = bg; } } if(fb & (0x80 >> (fdx & 7))) { - if (screenb.screen[pixeloffset] != fg) { + if (screenb.rect->data[pixeloffset] != fg) { screenb.update_pixels = 1; - screenb.screen[pixeloffset] = fg; - screenb.rect->data[pixeloffset] = color_value(fg); + screenb.rect->data[pixeloffset] = fg; } } else { - if (screenb.screen[pixeloffset] != bg) { + if (screenb.rect->data[pixeloffset] != bg) { screenb.update_pixels = 1; - screenb.screen[pixeloffset]=bg; - screenb.rect->data[pixeloffset] = color_value(bg); + screenb.rect->data[pixeloffset] = bg; } } pixeloffset++; @@ -657,7 +670,7 @@ static void blinker_thread(void *data) do { SLEEP(10); both_screens(&screen, &ncscreen); - } while (screen->screen == NULL); + } while (screen->rect == NULL); count++; if (count==25) { pthread_mutex_lock(&vstatlock); @@ -757,6 +770,7 @@ static int update_from_vmem(int force) struct vstat_vmem *vmem_ptr; int x,y,width,height; unsigned int pos; + int cols; int bright_attr_changed=0; int blink_attr_changed=0; @@ -800,6 +814,8 @@ static int update_from_vmem(int force) /* Get vmem pointer */ vmem_ptr = get_vmem(&vstat); + cols = vstat.cols; + pthread_mutex_unlock(&vstatlock); /* * Now we go through each character seeing if it's changed (or force is set) @@ -811,20 +827,20 @@ static int update_from_vmem(int force) */ for(y=0;y<height;y++) { - pos=y*vstat.cols; + pos=y*cols; for(x=0;x<width;x++) { /* Last this char been updated? */ if(force /* Forced */ - || ((vstat.vmem->vmem[pos].legacy_attr & 0x80) && blink_attr_changed) - || ((vstat.vmem->vmem[pos].legacy_attr & 0x08) && bright_attr_changed)) /* Bright char */ + || ((vmem_ptr->vmem[pos].legacy_attr & 0x80) && blink_attr_changed) + || ((vmem_ptr->vmem[pos].legacy_attr & 0x08) && bright_attr_changed)) /* Bright char */ { bitmap_draw_one_char(x+1,y+1); } pos++; } } + pthread_mutex_lock(&vstatlock); release_vmem(vmem_ptr); - pthread_mutex_unlock(&vstatlock); vs = vstat; @@ -848,12 +864,14 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill) pthread_mutex_lock(&vstatlock); vmem_ptr = get_vmem(&vstat); + pthread_mutex_unlock(&vstatlock); for(y=sy-1;y<ey;y++) { for(x=sx-1;x<ex;x++) { set_vmem_cell(vmem_ptr, y*cio_textinfo.screenwidth+x, *(buf++), 0x00ffffff, 0x00ffffff); bitmap_draw_one_char(x+1, y+1); } } + pthread_mutex_lock(&vstatlock); release_vmem(vmem_ptr); pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&blinker_lock); @@ -897,10 +915,12 @@ int bitmap_vmem_gettext(int sx, int sy, int ex, int ey, struct vmem_cell *fill) pthread_mutex_lock(&blinker_lock); pthread_mutex_lock(&vstatlock); vmem_ptr = get_vmem(&vstat); + pthread_mutex_unlock(&vstatlock); for(y=sy-1;y<ey;y++) { for(x=sx-1;x<ex;x++) memcpy(fill++, &vmem_ptr->vmem[y*cio_textinfo.screenwidth+x], sizeof(*fill)); } + pthread_mutex_lock(&vstatlock); release_vmem(vmem_ptr); pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&blinker_lock); @@ -1139,14 +1159,12 @@ bitmap_movetext_screen(struct bitmap_screen *screen, int x, int y, int tox, int pthread_mutex_lock(&screen->screenlock); if (width == cio_textinfo.screenwidth) { - memmove(&(screen->screen[ssourcepos+sdestoffset]), &(screen->screen[ssourcepos]), sizeof(screen->screen[0])*width*vstat.charwidth*height*vstat.charheight); - memmove(&(screen->rect->data[ssourcepos+sdestoffset]), &(screen->rect->data[ssourcepos]), sizeof(screen->screen[0])*width*vstat.charwidth*height*vstat.charheight); + memmove(&(screen->rect->data[ssourcepos+sdestoffset]), &(screen->rect->data[ssourcepos]), sizeof(screen->rect->data[0])*width*vstat.charwidth*height*vstat.charheight); } else { step = direction * vstat.scrnwidth; for(screeny=0; screeny < height*vstat.charheight; screeny++) { - memmove(&(screen->screen[ssourcepos+sdestoffset]), &(screen->screen[ssourcepos]), sizeof(screen->screen[0])*width*vstat.charwidth); - memmove(&(screen->rect->data[ssourcepos+sdestoffset]), &(screen->rect->data[ssourcepos]), sizeof(screen->screen[0])*width*vstat.charwidth); + memmove(&(screen->rect->data[ssourcepos+sdestoffset]), &(screen->rect->data[ssourcepos]), sizeof(screen->rect->data[0])*width*vstat.charwidth); ssourcepos += step; } } @@ -1195,10 +1213,7 @@ int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy) pthread_mutex_lock(&vstatlock); vmem_ptr = get_vmem(&vstat); - /* - * TODO: Optimization... make the buffers twice the height of the actual screen and just move the pointer - * when scrolling until you hit the end... maybe not worth it for vmem, but likely a big win for the screen - */ + pthread_mutex_unlock(&vstatlock); if (width == cio_textinfo.screenwidth) { memmove(&(vmem_ptr->vmem[sourcepos+destoffset]), &(vmem_ptr->vmem[sourcepos]), sizeof(vmem_ptr->vmem[0])*width*height); } @@ -1213,6 +1228,7 @@ int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy) bitmap_movetext_screen(&screena, x, y, tox, toy, direction, height, width); bitmap_movetext_screen(&screenb, x, y, tox, toy, direction, height, width); + pthread_mutex_lock(&vstatlock); release_vmem(vmem_ptr); pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&blinker_lock); @@ -1232,10 +1248,12 @@ void bitmap_clreol(void) pos=(row - 1)*cio_textinfo.screenwidth; pthread_mutex_lock(&vstatlock); vmem_ptr = get_vmem(&vstat); + pthread_mutex_unlock(&vstatlock); for(x=cio_textinfo.curx+cio_textinfo.winleft-2; x<cio_textinfo.winright; x++) { set_vmem_cell(vmem_ptr, pos+x, fill, ciolib_fg, ciolib_bg); bitmap_draw_one_char(x+1, row); } + pthread_mutex_lock(&vstatlock); release_vmem(vmem_ptr); pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&blinker_lock); @@ -1246,16 +1264,21 @@ void bitmap_clrscr(void) int x,y; WORD fill=(cio_textinfo.attribute<<8)|' '; struct vstat_vmem *vmem_ptr; + int rows, cols; pthread_mutex_lock(&blinker_lock); pthread_mutex_lock(&vstatlock); vmem_ptr = get_vmem(&vstat); - for(y = cio_textinfo.wintop-1; y < cio_textinfo.winbottom && y < vstat.rows; y++) { - for(x=cio_textinfo.winleft-1; x<cio_textinfo.winright && x < vstat.cols; x++) { + rows = vstat.rows; + cols = vstat.cols; + pthread_mutex_unlock(&vstatlock); + for(y = cio_textinfo.wintop-1; y < cio_textinfo.winbottom && y < rows; y++) { + for(x=cio_textinfo.winleft-1; x<cio_textinfo.winright && x < cols; x++) { set_vmem_cell(vmem_ptr, y*cio_textinfo.screenwidth+x, fill, ciolib_fg, ciolib_bg); bitmap_draw_one_char(x+1, y+1); } } + pthread_mutex_lock(&vstatlock); release_vmem(vmem_ptr); pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&blinker_lock); @@ -1374,20 +1397,18 @@ int bitmap_setpixel(uint32_t x, uint32_t y, uint32_t colour) pthread_mutex_lock(&screena.screenlock); if (x < screena.screenwidth && y < screena.screenheight) { - if (screena.screen[PIXEL_OFFSET(screena, x, y)] != colour) { - screena.screen[PIXEL_OFFSET(screena, x, y)]=colour; + if (screena.rect->data[PIXEL_OFFSET(screena, x, y)] != colour) { screena.update_pixels = 1; - screena.rect->data[PIXEL_OFFSET(screena, x, y)]=color_value(colour); + screena.rect->data[PIXEL_OFFSET(screena, x, y)] = colour; } } pthread_mutex_unlock(&screena.screenlock); pthread_mutex_lock(&screenb.screenlock); if (x < screenb.screenwidth && y < screenb.screenheight) { - if (screenb.screen[PIXEL_OFFSET(screenb, x, y)] != colour) { - screenb.screen[PIXEL_OFFSET(screenb, x, y)]=colour; + if (screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] != colour) { screenb.update_pixels = 1; - screenb.rect->data[PIXEL_OFFSET(screenb, x, y)]=color_value(colour); + screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = colour; } } pthread_mutex_unlock(&screenb.screenlock); @@ -1442,15 +1463,12 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_ pos = pixels->width*(y-sy+y_off)+x_off; if (mask == NULL) { for (x = sx; x <= ex; x++) { - screena.screen[PIXEL_OFFSET(screena, x, y)] = pixels->pixels[pos]; - screena.rect->data[PIXEL_OFFSET(screena, x, y)] = color_value(pixels->pixels[pos]); + screena.rect->data[PIXEL_OFFSET(screena, x, y)] = pixels->pixels[pos]; if (pixels->pixelsb) { - screenb.screen[PIXEL_OFFSET(screenb, x, y)] = pixels->pixelsb[pos]; - screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = color_value(pixels->pixelsb[pos]); + screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = pixels->pixelsb[pos]; } else { - screenb.screen[PIXEL_OFFSET(screenb, x, y)] = pixels->pixels[pos]; - screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = color_value(pixels->pixels[pos]); + screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = pixels->pixels[pos]; } pos++; } @@ -1462,15 +1480,12 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_ mask_bit = mpos % 8; mask_bit = 0x80 >> mask_bit; if (mask->bits[mask_byte] & mask_bit) { - screena.screen[PIXEL_OFFSET(screena, x, y)] = pixels->pixels[pos]; - screena.rect->data[PIXEL_OFFSET(screena, x, y)] = color_value(pixels->pixels[pos]); + screena.rect->data[PIXEL_OFFSET(screena, x, y)] = pixels->pixels[pos]; if (pixels->pixelsb) { - screenb.screen[PIXEL_OFFSET(screenb, x, y)] = pixels->pixelsb[pos]; - screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = color_value(pixels->pixelsb[pos]); + screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = pixels->pixelsb[pos]; } else { - screenb.screen[PIXEL_OFFSET(screenb, x, y)] = pixels->pixels[pos]; - screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = color_value(pixels->pixels[pos]); + screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = pixels->pixels[pos]; } } pos++; @@ -1522,14 +1537,12 @@ struct ciolib_pixels *bitmap_getpixels(uint32_t sx, uint32_t sy, uint32_t ex, ui pthread_mutex_lock(&blinker_lock); update_from_vmem(force); - pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&screena.screenlock); pthread_mutex_lock(&screenb.screenlock); if (ex >= screena.screenwidth || ey >= screena.screenheight || ex >= screenb.screenwidth || ey >= screenb.screenheight) { pthread_mutex_unlock(&screenb.screenlock); pthread_mutex_unlock(&screena.screenlock); - pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&blinker_lock); free(pixels->pixelsb); free(pixels->pixels); @@ -1538,12 +1551,12 @@ struct ciolib_pixels *bitmap_getpixels(uint32_t sx, uint32_t sy, uint32_t ex, ui } for (y = sy; y <= ey; y++) { - memcpy(&pixels->pixels[width*(y-sy)], &screena.screen[PIXEL_OFFSET(screena, sx, y)], width * sizeof(pixels->pixels[0])); - memcpy(&pixels->pixelsb[width*(y-sy)], &screenb.screen[PIXEL_OFFSET(screenb, sx, y)], width * sizeof(pixels->pixelsb[0])); + // TODO: This is the place where screen vs. buffer matters. :( + memcpy(&pixels->pixels[width*(y-sy)], &screena.rect->data[PIXEL_OFFSET(screena, sx, y)], width * sizeof(pixels->pixels[0])); + memcpy(&pixels->pixelsb[width*(y-sy)], &screenb.rect->data[PIXEL_OFFSET(screenb, sx, y)], width * sizeof(pixels->pixelsb[0])); } pthread_mutex_unlock(&screenb.screenlock); pthread_mutex_unlock(&screena.screenlock); - pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&blinker_lock); return pixels; @@ -1633,8 +1646,6 @@ int bitmap_setpalette(uint32_t index, uint16_t r, uint16_t g, uint16_t b) // Called with vstatlock static int init_screen(struct bitmap_screen *screen, int *width, int *height) { - uint32_t *newbuf; - pthread_mutex_lock(&screen->screenlock); screen->screenwidth = vstat.scrnwidth; if (width) @@ -1642,14 +1653,6 @@ static int init_screen(struct bitmap_screen *screen, int *width, int *height) screen->screenheight = vstat.scrnheight; if (height) *height = screen->screenheight; - newbuf = realloc(screen->screen, screen->screenwidth * screen->screenheight * 2 * sizeof(screen->screen[0])); - - if (!newbuf) { - pthread_mutex_unlock(&screen->screenlock); - return(-1); - } - memset_u32(newbuf, vstat.palette[0], screen->screenwidth * 2 * screen->screenheight); - screen->screen = newbuf; screen->update_pixels = 1; bitmap_drv_free_rect(screen->rect); screen->rect = alloc_full_rect(screen);