Mercurial > repos > blastem
comparison render_fbdev.c @ 1785:8f2e78db0872
Handle interlaced mode in fbdev backend
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 14 Mar 2019 23:23:02 -0700 |
parents | b2bffd98063d |
children | 2b661c1e431f |
comparison
equal
deleted
inserted
replaced
1784:72540af9c90a | 1785:8f2e78db0872 |
---|---|
428 } | 428 } |
429 return ret; | 429 return ret; |
430 } | 430 } |
431 #endif | 431 #endif |
432 | 432 |
433 static uint32_t texture_buf[513 * 512 * 2]; | 433 #define MAX_FB_LINES 590 |
434 static uint32_t texture_buf[MAX_FB_LINES * LINEBUF_SIZE * 2]; | |
434 #ifdef DISABLE_OPENGL | 435 #ifdef DISABLE_OPENGL |
435 #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888 | 436 #define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888 |
436 #else | 437 #else |
437 #ifdef USE_GLES | 438 #ifdef USE_GLES |
438 #define INTERNAL_FORMAT GL_RGBA | 439 #define INTERNAL_FORMAT GL_RGBA |
1082 #endif | 1083 #endif |
1083 static pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER; | 1084 static pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER; |
1084 static pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER; | 1085 static pthread_cond_t buffer_cond = PTHREAD_COND_INITIALIZER; |
1085 static uint8_t buffer_ready; | 1086 static uint8_t buffer_ready; |
1086 static uint32_t *copy_buffer; | 1087 static uint32_t *copy_buffer; |
1087 static uint32_t last_width, last_width_scale, last_height; | 1088 static uint32_t last_width, last_width_scale, last_height, last_height_scale; |
1088 static uint32_t max_multiple; | 1089 static uint32_t max_multiple; |
1090 | |
1091 static uint32_t mix_pixel(uint32_t last, uint32_t cur, float ratio) | |
1092 { | |
1093 float a,b,c,d; | |
1094 a = (last & 255) * ratio; | |
1095 b = (last >> 8 & 255) * ratio; | |
1096 c = (last >> 16 & 255) * ratio; | |
1097 d = (last >> 24 & 255) * ratio; | |
1098 ratio = 1.0f - ratio; | |
1099 a += (cur & 255) * ratio; | |
1100 b += (cur >> 8 & 255) * ratio; | |
1101 c += (cur >> 16 & 255) * ratio; | |
1102 d += (cur >> 24 & 255) * ratio; | |
1103 return ((int)d) << 24 | ((int)c) << 16 | ((int)b) << 8 | ((int)a); | |
1104 } | |
1089 static void do_buffer_copy(void) | 1105 static void do_buffer_copy(void) |
1090 { | 1106 { |
1091 uint32_t width_multiple = main_width / last_width_scale; | 1107 uint32_t width_multiple = main_width / last_width_scale; |
1092 uint32_t height_multiple = main_height / last_height; | 1108 uint32_t height_multiple = main_height / last_height_scale; |
1093 uint32_t multiple = width_multiple < height_multiple ? width_multiple : height_multiple; | 1109 uint32_t multiple = width_multiple < height_multiple ? width_multiple : height_multiple; |
1094 if (max_multiple && multiple > max_multiple) { | 1110 if (max_multiple && multiple > max_multiple) { |
1095 multiple = max_multiple; | 1111 multiple = max_multiple; |
1096 } | 1112 } |
1113 height_multiple = last_height_scale * multiple / last_height; | |
1097 uint32_t *cur_line = framebuffer + (main_width - last_width_scale * multiple)/2; | 1114 uint32_t *cur_line = framebuffer + (main_width - last_width_scale * multiple)/2; |
1098 cur_line += fb_stride * (main_height - last_height * multiple) / (2 * sizeof(uint32_t)); | 1115 cur_line += fb_stride * (main_height - last_height_scale * multiple) / (2 * sizeof(uint32_t)); |
1099 uint32_t *src_line = copy_buffer; | 1116 uint32_t *src_line = copy_buffer; |
1100 if (last_width == last_width_scale) { | 1117 if (height_multiple * last_height == multiple * last_height_scale) { |
1101 for (uint32_t y = 0; y < last_height; y++) | 1118 if (last_width == last_width_scale) { |
1102 { | 1119 for (uint32_t y = 0; y < last_height; y++) |
1103 for (uint32_t i = 0; i < multiple; i++) | |
1104 { | 1120 { |
1105 uint32_t *cur = cur_line; | 1121 for (uint32_t i = 0; i < height_multiple; i++) |
1106 uint32_t *src = src_line; | |
1107 for (uint32_t x = 0; x < last_width ; x++) | |
1108 { | 1122 { |
1109 uint32_t pixel = *(src++); | 1123 uint32_t *cur = cur_line; |
1110 for (uint32_t j = 0; j < multiple; j++) | 1124 uint32_t *src = src_line; |
1125 for (uint32_t x = 0; x < last_width ; x++) | |
1111 { | 1126 { |
1112 *(cur++) = pixel; | 1127 uint32_t pixel = *(src++); |
1128 for (uint32_t j = 0; j < multiple; j++) | |
1129 { | |
1130 *(cur++) = pixel; | |
1131 } | |
1113 } | 1132 } |
1133 | |
1134 cur_line += fb_stride / sizeof(uint32_t); | |
1135 } | |
1136 src_line += LINEBUF_SIZE; | |
1137 } | |
1138 } else { | |
1139 float scale_multiple = ((float)(last_width_scale * multiple)) / (float)last_width; | |
1140 float remaining = 0.0f; | |
1141 uint32_t last_pixel = 0; | |
1142 for (uint32_t y = 0; y < last_height; y++) | |
1143 { | |
1144 for (uint32_t i = 0; i < height_multiple; i++) | |
1145 { | |
1146 uint32_t *cur = cur_line; | |
1147 uint32_t *src = src_line; | |
1148 for (uint32_t x = 0; x < last_width ; x++) | |
1149 { | |
1150 uint32_t pixel = *(src++); | |
1151 float count = scale_multiple; | |
1152 if (remaining > 0.0f) { | |
1153 *(cur++) = mix_pixel(last_pixel, pixel, remaining); | |
1154 count -= 1.0f - remaining; | |
1155 } | |
1156 for (; count >= 1; count -= 1.0f) | |
1157 { | |
1158 *(cur++) = pixel; | |
1159 } | |
1160 remaining = count; | |
1161 last_pixel = pixel; | |
1162 } | |
1163 | |
1164 cur_line += fb_stride / sizeof(uint32_t); | |
1165 } | |
1166 src_line += LINEBUF_SIZE; | |
1167 } | |
1168 } | |
1169 } else { | |
1170 float height_scale = ((float)(last_height_scale * multiple)) / (float)last_height; | |
1171 float height_remaining = 0.0f; | |
1172 uint32_t *last_line; | |
1173 if (last_width == last_width_scale) { | |
1174 for (uint32_t y = 0; y < last_height; y++) | |
1175 { | |
1176 float hcount = height_scale; | |
1177 if (height_remaining > 0.0f) { | |
1178 uint32_t *cur = cur_line; | |
1179 uint32_t *src = src_line; | |
1180 uint32_t *last = last_line; | |
1181 for (uint32_t x = 0; x < last_width ; x++) | |
1182 { | |
1183 uint32_t mixed = mix_pixel(*(last++), *(src++), height_remaining); | |
1184 for (uint32_t j = 0; j < multiple; j++) | |
1185 { | |
1186 *(cur++) = mixed; | |
1187 } | |
1188 } | |
1189 hcount -= 1.0f - height_remaining; | |
1190 cur_line += fb_stride / sizeof(uint32_t); | |
1191 } | |
1192 for(; hcount >= 1; hcount -= 1.0f) | |
1193 { | |
1194 uint32_t *cur = cur_line; | |
1195 uint32_t *src = src_line; | |
1196 for (uint32_t x = 0; x < last_width ; x++) | |
1197 { | |
1198 uint32_t pixel = *(src++); | |
1199 for (uint32_t j = 0; j < multiple; j++) | |
1200 { | |
1201 *(cur++) = pixel; | |
1202 } | |
1203 } | |
1204 | |
1205 cur_line += fb_stride / sizeof(uint32_t); | |
1206 } | |
1207 height_remaining = hcount; | |
1208 last_line = src_line; | |
1209 src_line += LINEBUF_SIZE; | |
1210 } | |
1211 } else { | |
1212 float scale_multiple = ((float)(last_width_scale * multiple)) / (float)last_width; | |
1213 float remaining = 0.0f; | |
1214 uint32_t last_pixel = 0; | |
1215 for (uint32_t y = 0; y < last_height; y++) | |
1216 { | |
1217 float hcount = height_scale; | |
1218 if (height_remaining > 0.0f) { | |
1219 uint32_t *cur = cur_line; | |
1220 uint32_t *src = src_line; | |
1221 uint32_t *last = last_line; | |
1222 | |
1223 for (uint32_t x = 0; x < last_width; x++) | |
1224 { | |
1225 uint32_t pixel = mix_pixel(*(last++), *(src++), height_remaining); | |
1226 float count = scale_multiple; | |
1227 if (remaining > 0.0f) { | |
1228 *(cur++) = mix_pixel(last_pixel, pixel, remaining); | |
1229 count -= 1.0f - remaining; | |
1230 } | |
1231 for (; count >= 1.0f; count -= 1.0f) | |
1232 { | |
1233 *(cur++) = pixel; | |
1234 } | |
1235 remaining = count; | |
1236 last_pixel = pixel; | |
1237 } | |
1238 hcount -= 1.0f - height_remaining; | |
1239 cur_line += fb_stride / sizeof(uint32_t); | |
1114 } | 1240 } |
1115 | 1241 |
1116 cur_line += fb_stride / sizeof(uint32_t); | 1242 for (; hcount >= 1.0f; hcount -= 1.0f) |
1117 } | |
1118 src_line += LINEBUF_SIZE; | |
1119 } | |
1120 } else { | |
1121 float scale_multiple = ((float)(last_width_scale * multiple)) / (float)last_width; | |
1122 float remaining = 0.0f; | |
1123 uint32_t last_pixel = 0; | |
1124 for (uint32_t y = 0; y < last_height; y++) | |
1125 { | |
1126 for (uint32_t i = 0; i < multiple; i++) | |
1127 { | |
1128 uint32_t *cur = cur_line; | |
1129 uint32_t *src = src_line; | |
1130 for (uint32_t x = 0; x < last_width ; x++) | |
1131 { | 1243 { |
1132 uint32_t pixel = *(src++); | 1244 uint32_t *cur = cur_line; |
1133 float count = scale_multiple; | 1245 uint32_t *src = src_line; |
1134 if (remaining > 0.0f) { | 1246 for (uint32_t x = 0; x < last_width ; x++) |
1135 float a,b,c,d; | 1247 { |
1136 a = (last_pixel & 255) * remaining; | 1248 uint32_t pixel = *(src++); |
1137 b = (last_pixel >> 8 & 255) * remaining; | 1249 float count = scale_multiple; |
1138 c = (last_pixel >> 16 & 255) * remaining; | 1250 if (remaining > 0.0f) { |
1139 d = (last_pixel >> 24 & 255) * remaining; | 1251 *(cur++) = mix_pixel(last_pixel, pixel, remaining); |
1140 remaining = 1.0f - remaining; | 1252 count -= 1.0f - remaining; |
1141 a += (pixel & 255) * remaining; | 1253 } |
1142 b += (pixel >> 8 & 255) * remaining; | 1254 for (; count >= 1; count -= 1.0f) |
1143 c += (pixel >> 16 & 255) * remaining; | 1255 { |
1144 d += (pixel >> 24 & 255) * remaining; | 1256 *(cur++) = pixel; |
1145 count -= remaining; | 1257 } |
1146 uint32_t mixed = ((int)d) << 24 | ((int)c) << 16 | ((int)b) << 8 | ((int)a); | 1258 remaining = count; |
1147 *(cur++) = mixed; | 1259 last_pixel = pixel; |
1148 } | 1260 } |
1149 for (; count >= 1; count -= 1.0f) | 1261 |
1150 { | 1262 cur_line += fb_stride / sizeof(uint32_t); |
1151 *(cur++) = pixel; | |
1152 } | |
1153 remaining = count; | |
1154 last_pixel = pixel; | |
1155 } | 1263 } |
1156 | 1264 height_remaining = hcount; |
1157 cur_line += fb_stride / sizeof(uint32_t); | 1265 last_line = src_line; |
1158 } | 1266 src_line += LINEBUF_SIZE; |
1159 src_line += LINEBUF_SIZE; | 1267 } |
1160 } | 1268 } |
1161 } | 1269 } |
1162 } | 1270 } |
1163 static void *buffer_copy(void *data) | 1271 static void *buffer_copy(void *data) |
1164 { | 1272 { |
1545 void render_destroy_window(uint8_t which) | 1653 void render_destroy_window(uint8_t which) |
1546 { | 1654 { |
1547 //not supported under fbdev | 1655 //not supported under fbdev |
1548 } | 1656 } |
1549 | 1657 |
1550 uint32_t *locked_pixels; | 1658 static uint8_t last_fb; |
1551 uint32_t locked_pitch; | 1659 static uint32_t texture_off; |
1552 uint32_t texture_off; | |
1553 uint32_t *render_get_framebuffer(uint8_t which, int *pitch) | 1660 uint32_t *render_get_framebuffer(uint8_t which, int *pitch) |
1554 { | 1661 { |
1555 if (max_multiple == 1 && !render_gl) { | 1662 if (max_multiple == 1 && !render_gl) { |
1663 if (last_fb != which) { | |
1664 *pitch = fb_stride * 2; | |
1665 return framebuffer + (which == FRAMEBUFFER_EVEN ? fb_stride / sizeof(uint32_t) : 0); | |
1666 } | |
1556 *pitch = fb_stride; | 1667 *pitch = fb_stride; |
1557 return framebuffer; | 1668 return framebuffer; |
1558 } | 1669 } |
1670 if (!render_gl && last_fb != which) { | |
1671 *pitch = LINEBUF_SIZE * sizeof(uint32_t) * 2; | |
1672 return texture_buf + texture_off + (which == FRAMEBUFFER_EVEN ? LINEBUF_SIZE : 0); | |
1673 } | |
1559 *pitch = LINEBUF_SIZE * sizeof(uint32_t); | 1674 *pitch = LINEBUF_SIZE * sizeof(uint32_t); |
1560 return texture_buf + texture_off; | 1675 return texture_buf + texture_off; |
1561 /* | |
1562 #ifndef DISABLE_OPENGL | |
1563 if (render_gl && which <= FRAMEBUFFER_EVEN) { | |
1564 *pitch = LINEBUF_SIZE * sizeof(uint32_t); | |
1565 return texture_buf; | |
1566 } else { | |
1567 #endif | |
1568 if (which >= num_textures) { | |
1569 warning("Request for invalid framebuffer number %d\n", which); | |
1570 return NULL; | |
1571 } | |
1572 void *pixels; | |
1573 if (SDL_LockTexture(sdl_textures[which], NULL, &pixels, pitch) < 0) { | |
1574 warning("Failed to lock texture: %s\n", SDL_GetError()); | |
1575 return NULL; | |
1576 } | |
1577 static uint8_t last; | |
1578 if (which <= FRAMEBUFFER_EVEN) { | |
1579 locked_pixels = pixels; | |
1580 if (which == FRAMEBUFFER_EVEN) { | |
1581 pixels += *pitch; | |
1582 } | |
1583 locked_pitch = *pitch; | |
1584 if (which != last) { | |
1585 *pitch *= 2; | |
1586 } | |
1587 last = which; | |
1588 } | |
1589 return pixels; | |
1590 #ifndef DISABLE_OPENGL | |
1591 } | |
1592 #endif*/ | |
1593 } | 1676 } |
1594 | 1677 |
1595 uint8_t events_processed; | 1678 uint8_t events_processed; |
1596 #ifdef __ANDROID__ | 1679 #ifdef __ANDROID__ |
1597 #define FPS_INTERVAL 10000 | 1680 #define FPS_INTERVAL 10000 |
1620 if (copy_use_thread) { | 1703 if (copy_use_thread) { |
1621 pthread_mutex_lock(&buffer_lock); | 1704 pthread_mutex_lock(&buffer_lock); |
1622 buffer_ready = 1; | 1705 buffer_ready = 1; |
1623 last_width = width; | 1706 last_width = width; |
1624 last_width_scale = LINEBUF_SIZE - (overscan_left[video_standard] + overscan_right[video_standard]); | 1707 last_width_scale = LINEBUF_SIZE - (overscan_left[video_standard] + overscan_right[video_standard]); |
1625 last_height = height; | 1708 last_height = last_height_scale = height; |
1626 copy_buffer = texture_buf + texture_off + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]; | 1709 copy_buffer = texture_buf + texture_off + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]; |
1627 texture_off = texture_off ? 0 : LINEBUF_SIZE * 512; | 1710 if (which != last_fb) { |
1711 last_height *= 2; | |
1712 copy_buffer += LINEBUF_SIZE * overscan_top[video_standard]; | |
1713 uint32_t *src = texture_buf + (texture_off ? 0 : LINEBUF_SIZE * MAX_FB_LINES) + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]; | |
1714 uint32_t *dst = copy_buffer; | |
1715 if (which == FRAMEBUFFER_ODD) { | |
1716 src += LINEBUF_SIZE; | |
1717 dst += LINEBUF_SIZE; | |
1718 } | |
1719 for (int i = 0; i < height; i++) | |
1720 { | |
1721 memcpy(dst, src, width * sizeof(uint32_t)); | |
1722 src += LINEBUF_SIZE * 2; | |
1723 dst += LINEBUF_SIZE * 2; | |
1724 } | |
1725 } | |
1726 texture_off = texture_off ? 0 : LINEBUF_SIZE * MAX_FB_LINES; | |
1628 pthread_cond_signal(&buffer_cond); | 1727 pthread_cond_signal(&buffer_cond); |
1629 pthread_mutex_unlock(&buffer_lock); | 1728 pthread_mutex_unlock(&buffer_lock); |
1630 } else { | 1729 } else { |
1631 last_width = width; | 1730 last_width = width; |
1632 last_width_scale = LINEBUF_SIZE - (overscan_left[video_standard] + overscan_right[video_standard]); | 1731 last_width_scale = LINEBUF_SIZE - (overscan_left[video_standard] + overscan_right[video_standard]); |
1633 last_height = height; | 1732 last_height = last_height_scale = height; |
1634 copy_buffer = texture_buf + texture_off + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]; | 1733 copy_buffer = texture_buf + texture_off + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]; |
1734 if (which != last_fb) { | |
1735 last_height *= 2; | |
1736 copy_buffer += LINEBUF_SIZE * overscan_top[video_standard]; | |
1737 } | |
1635 do_buffer_copy(); | 1738 do_buffer_copy(); |
1636 } | 1739 } |
1637 } | 1740 } |
1741 last_fb = which; | |
1638 if (!events_processed) { | 1742 if (!events_processed) { |
1639 process_events(); | 1743 process_events(); |
1640 } | 1744 } |
1641 events_processed = 0; | 1745 events_processed = 0; |
1642 #ifndef DISABLE_OPENGL | 1746 #ifndef DISABLE_OPENGL |