Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
Michael Sevakis | 441fca1 | 2008-12-10 21:10:34 +0000 | [diff] [blame] | 8 | * $Id$ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 9 | * |
| 10 | * Copyright (C) 2008 by Akio Idehara, Andrew Mahone |
| 11 | * |
| 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
| 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | |
| 22 | /* |
| 23 | * Implementation of area average and linear row and vertical scalers, and |
| 24 | * nearest-neighbor grey scaler (C) 2008 Andrew Mahone |
| 25 | * |
| 26 | * All files in this archive are subject to the GNU General Public License. |
| 27 | * See the file COPYING in the source tree root for full license agreement. |
| 28 | * |
| 29 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 30 | * KIND, either express or implied. |
| 31 | * |
| 32 | ****************************************************************************/ |
| 33 | |
Andrew Mahone | 2fbf097 | 2009-01-13 13:48:26 +0000 | [diff] [blame] | 34 | #include <system.h> |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 35 | #include <stdio.h> |
| 36 | #include <stdlib.h> |
| 37 | #include <string.h> |
Andrew Mahone | 524c540 | 2008-12-14 17:58:04 +0000 | [diff] [blame] | 38 | #include <general.h> |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 39 | #include "inttypes.h" |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 40 | #ifndef PLUGIN |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 41 | #include "debug.h" |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 42 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 43 | #include "lcd.h" |
| 44 | #include "file.h" |
| 45 | #ifdef HAVE_REMOTE_LCD |
| 46 | #include "lcd-remote.h" |
| 47 | #endif |
| 48 | #ifdef ROCKBOX_DEBUG_SCALERS |
| 49 | #define SDEBUGF DEBUGF |
| 50 | #else |
| 51 | #define SDEBUGF(...) |
| 52 | #endif |
| 53 | #ifndef __PCTOOL__ |
| 54 | #include "config.h" |
| 55 | #include "system.h" |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 56 | #include <bmp.h> |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 57 | #include "resize.h" |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 58 | #else |
| 59 | #undef DEBUGF |
| 60 | #define DEBUGF(...) |
| 61 | #endif |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 62 | #include <jpeg_load.h> |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 63 | |
Andrew Mahone | f8877bf | 2009-03-14 01:41:02 +0000 | [diff] [blame] | 64 | #if CONFIG_CPU == SH7034 |
| 65 | /* 16*16->32 bit multiplication is a single instrcution on the SH1 */ |
| 66 | #define MULUQ(a, b) ((uint32_t) (((uint16_t) (a)) * ((uint16_t) (b)))) |
| 67 | #define MULQ(a, b) ((int32_t) (((int16_t) (a)) * ((int16_t) (b)))) |
| 68 | #else |
| 69 | #define MULUQ(a, b) ((a) * (b)) |
| 70 | #define MULQ(a, b) ((a) * (b)) |
| 71 | #endif |
| 72 | |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 73 | /* calculate the maximum dimensions which will preserve the aspect ration of |
| 74 | src while fitting in the constraints passed in dst, and store result in dst, |
| 75 | returning 0 if rounding and 1 if not rounding. |
| 76 | */ |
| 77 | int recalc_dimension(struct dim *dst, struct dim *src) |
| 78 | { |
Andrew Mahone | 738a564 | 2009-01-13 14:41:29 +0000 | [diff] [blame] | 79 | /* This only looks backwards. The input image size is being pre-scaled by |
| 80 | * the inverse of the pixel aspect ratio, so that once the size it scaled |
| 81 | * to meet the output constraints, the scaled image will have appropriate |
| 82 | * proportions. |
| 83 | */ |
| 84 | int sw = src->width * LCD_PIXEL_ASPECT_HEIGHT; |
| 85 | int sh = src->height * LCD_PIXEL_ASPECT_WIDTH; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 86 | int tmp; |
| 87 | if (dst->width <= 0) |
| 88 | dst->width = LCD_WIDTH; |
| 89 | if (dst->height <= 0) |
| 90 | dst->height = LCD_HEIGHT; |
| 91 | #ifndef HAVE_UPSCALER |
Andrew Mahone | 738a564 | 2009-01-13 14:41:29 +0000 | [diff] [blame] | 92 | if (dst->width > sw || dst->height > sh) |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 93 | { |
Andrew Mahone | 738a564 | 2009-01-13 14:41:29 +0000 | [diff] [blame] | 94 | dst->width = sw; |
| 95 | dst->height = sh; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 96 | } |
Andrew Mahone | 738a564 | 2009-01-13 14:41:29 +0000 | [diff] [blame] | 97 | if (sw == dst->width && sh == dst->height) |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 98 | return 1; |
| 99 | #endif |
Andrew Mahone | 738a564 | 2009-01-13 14:41:29 +0000 | [diff] [blame] | 100 | tmp = (sw * dst->height + (sh >> 1)) / sh; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 101 | if (tmp > dst->width) |
Andrew Mahone | 738a564 | 2009-01-13 14:41:29 +0000 | [diff] [blame] | 102 | dst->height = (sh * dst->width + (sw >> 1)) / sw; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 103 | else |
| 104 | dst->width = tmp; |
| 105 | return src->width == dst->width && src->height == dst->height; |
| 106 | } |
| 107 | |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 108 | /* All of these scalers use variations of Bresenham's algorithm to convert from |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 109 | their input to output coordinates. The error value is shifted from the |
| 110 | "classic" version such that it is a useful input to the scaling calculation. |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 111 | */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 112 | |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 113 | #ifdef HAVE_LCD_COLOR |
| 114 | /* dither + pack on channel of RGB565, R an B share a packing macro */ |
| 115 | #define PACKRB(v, delta) ((31 * v + (v >> 3) + delta) >> 8) |
| 116 | #define PACKG(g, delta) ((63 * g + (g >> 2) + delta) >> 8) |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 117 | #endif |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 118 | |
| 119 | /* read new img_part unconditionally, return false on failure */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 120 | #define FILL_BUF_INIT(img_part, store_part, args) { \ |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 121 | img_part = store_part(args); \ |
| 122 | if (img_part == NULL) \ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 123 | return false; \ |
| 124 | } |
| 125 | |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 126 | /* read new img_part if current one is empty, return false on failure */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 127 | #define FILL_BUF(img_part, store_part, args) { \ |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 128 | if (img_part->len == 0) \ |
| 129 | img_part = store_part(args); \ |
| 130 | if (img_part == NULL) \ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 131 | return false; \ |
| 132 | } |
| 133 | |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 134 | #if defined(CPU_COLDFIRE) |
| 135 | #define MAC(op1, op2, num) \ |
| 136 | asm volatile( \ |
| 137 | "mac.l %0, %1, %%acc" #num \ |
| 138 | : \ |
| 139 | : "%d" (op1), "d" (op2)\ |
| 140 | ) |
| 141 | #define MAC_OUT(dest, num) \ |
| 142 | asm volatile( \ |
| 143 | "movclr.l %%acc" #num ", %0" \ |
| 144 | : "=d" (dest) \ |
| 145 | ) |
| 146 | #elif defined(CPU_SH) |
| 147 | /* calculate the 32-bit product of unsigned 16-bit op1 and op2 */ |
| 148 | static inline int32_t mul_s16_s16(int16_t op1, int16_t op2) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 149 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 150 | return (int32_t)(op1 * op2); |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 151 | } |
| 152 | |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 153 | /* calculate the 32-bit product of signed 16-bit op1 and op2 */ |
| 154 | static inline uint32_t mul_u16_u16(uint16_t op1, uint16_t op2) |
| 155 | { |
| 156 | return (uint32_t)(op1 * op2); |
| 157 | } |
| 158 | #endif |
| 159 | |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 160 | /* horizontal area average scaler */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 161 | static bool scale_h_area(void *out_line_ptr, |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 162 | struct scaler_context *ctx, bool accum) |
| 163 | { |
| 164 | SDEBUGF("scale_h_area\n"); |
| 165 | unsigned int ix, ox, oxe, mul; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 166 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 167 | const uint32_t h_i_val = ctx->src->width, |
| 168 | h_o_val = ctx->bm->width; |
| 169 | #else |
| 170 | const uint32_t h_i_val = ctx->h_i_val, |
| 171 | h_o_val = ctx->h_o_val; |
| 172 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 173 | #ifdef HAVE_LCD_COLOR |
| 174 | struct uint32_rgb rgbvalacc = { 0, 0, 0 }, |
| 175 | rgbvaltmp = { 0, 0, 0 }, |
| 176 | *out_line = (struct uint32_rgb *)out_line_ptr; |
| 177 | #else |
| 178 | uint32_t acc = 0, tmp = 0, *out_line = (uint32_t*)out_line_ptr; |
| 179 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 180 | struct img_part *part; |
| 181 | FILL_BUF_INIT(part,ctx->store_part,ctx->args); |
| 182 | ox = 0; |
| 183 | oxe = 0; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 184 | mul = 0; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 185 | /* give other tasks a chance to run */ |
Andrew Mahone | 07e982d | 2009-01-08 02:49:23 +0000 | [diff] [blame] | 186 | yield(); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 187 | for (ix = 0; ix < (unsigned int)ctx->src->width; ix++) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 188 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 189 | oxe += h_o_val; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 190 | /* end of current area has been reached */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 191 | /* fill buffer if needed */ |
| 192 | FILL_BUF(part,ctx->store_part,ctx->args); |
| 193 | #ifdef HAVE_LCD_COLOR |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 194 | if (oxe >= h_i_val) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 195 | { |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 196 | /* "reset" error, which now represents partial coverage of next |
| 197 | pixel by the next area |
| 198 | */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 199 | oxe -= h_i_val; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 200 | |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 201 | #if defined(CPU_COLDFIRE) |
| 202 | /* Coldfire EMAC math */ |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 203 | /* add saved partial pixel from start of area */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 204 | MAC(rgbvalacc.r, h_o_val, 0); |
| 205 | MAC(rgbvalacc.g, h_o_val, 1); |
| 206 | MAC(rgbvalacc.b, h_o_val, 2); |
| 207 | MAC(rgbvaltmp.r, mul, 0); |
| 208 | MAC(rgbvaltmp.g, mul, 1); |
| 209 | MAC(rgbvaltmp.b, mul, 2); |
| 210 | /* get new pixel , then add its partial coverage to this area */ |
| 211 | mul = h_o_val - oxe; |
| 212 | rgbvaltmp.r = part->buf->red; |
| 213 | rgbvaltmp.g = part->buf->green; |
| 214 | rgbvaltmp.b = part->buf->blue; |
| 215 | MAC(rgbvaltmp.r, mul, 0); |
| 216 | MAC(rgbvaltmp.g, mul, 1); |
| 217 | MAC(rgbvaltmp.b, mul, 2); |
| 218 | MAC_OUT(rgbvalacc.r, 0); |
| 219 | MAC_OUT(rgbvalacc.g, 1); |
| 220 | MAC_OUT(rgbvalacc.b, 2); |
| 221 | #else |
| 222 | /* generic C math */ |
| 223 | /* add saved partial pixel from start of area */ |
| 224 | rgbvalacc.r = rgbvalacc.r * h_o_val + rgbvaltmp.r * mul; |
| 225 | rgbvalacc.g = rgbvalacc.g * h_o_val + rgbvaltmp.g * mul; |
| 226 | rgbvalacc.b = rgbvalacc.b * h_o_val + rgbvaltmp.b * mul; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 227 | |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 228 | /* get new pixel , then add its partial coverage to this area */ |
| 229 | rgbvaltmp.r = part->buf->red; |
| 230 | rgbvaltmp.g = part->buf->green; |
| 231 | rgbvaltmp.b = part->buf->blue; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 232 | mul = h_o_val - oxe; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 233 | rgbvalacc.r += rgbvaltmp.r * mul; |
| 234 | rgbvalacc.g += rgbvaltmp.g * mul; |
| 235 | rgbvalacc.b += rgbvaltmp.b * mul; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 236 | #endif /* CPU */ |
| 237 | rgbvalacc.r = (rgbvalacc.r + (1 << 21)) >> 22; |
| 238 | rgbvalacc.g = (rgbvalacc.g + (1 << 21)) >> 22; |
| 239 | rgbvalacc.b = (rgbvalacc.b + (1 << 21)) >> 22; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 240 | /* store or accumulate to output row */ |
| 241 | if (accum) |
| 242 | { |
| 243 | rgbvalacc.r += out_line[ox].r; |
| 244 | rgbvalacc.g += out_line[ox].g; |
| 245 | rgbvalacc.b += out_line[ox].b; |
| 246 | } |
| 247 | out_line[ox].r = rgbvalacc.r; |
| 248 | out_line[ox].g = rgbvalacc.g; |
| 249 | out_line[ox].b = rgbvalacc.b; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 250 | /* reset accumulator */ |
| 251 | rgbvalacc.r = 0; |
| 252 | rgbvalacc.g = 0; |
| 253 | rgbvalacc.b = 0; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 254 | mul = oxe; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 255 | ox += 1; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 256 | /* inside an area */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 257 | } else { |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 258 | /* add pixel value to accumulator */ |
| 259 | rgbvalacc.r += part->buf->red; |
| 260 | rgbvalacc.g += part->buf->green; |
| 261 | rgbvalacc.b += part->buf->blue; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 262 | } |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 263 | #else |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 264 | if (oxe >= h_i_val) |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 265 | { |
| 266 | /* "reset" error, which now represents partial coverage of next |
| 267 | pixel by the next area |
| 268 | */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 269 | oxe -= h_i_val; |
| 270 | #if defined(CPU_COLDFIRE) |
| 271 | /* Coldfire EMAC math */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 272 | /* add saved partial pixel from start of area */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 273 | MAC(acc, h_o_val, 0); |
| 274 | MAC(tmp, mul, 0); |
| 275 | /* get new pixel , then add its partial coverage to this area */ |
| 276 | tmp = *(part->buf); |
| 277 | mul = h_o_val - oxe; |
| 278 | MAC(tmp, mul, 0); |
| 279 | MAC_OUT(acc, 0); |
| 280 | #elif defined(CPU_SH) |
| 281 | /* SH-1 16x16->32 math */ |
| 282 | /* add saved partial pixel from start of area */ |
| 283 | acc = mul_u16_u16(acc, h_o_val) + mul_u16_u16(tmp, mul); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 284 | |
| 285 | /* get new pixel , then add its partial coverage to this area */ |
| 286 | tmp = *(part->buf); |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 287 | mul = h_o_val - oxe; |
| 288 | acc += mul_u16_u16(tmp, mul); |
| 289 | #else |
| 290 | /* generic C math */ |
| 291 | /* add saved partial pixel from start of area */ |
| 292 | acc = (acc * h_o_val) + (tmp * mul); |
| 293 | |
| 294 | /* get new pixel , then add its partial coverage to this area */ |
| 295 | tmp = *(part->buf); |
| 296 | mul = h_o_val - oxe; |
| 297 | acc += tmp * mul; |
| 298 | #endif /* CPU */ |
| 299 | #if !(defined(CPU_SH) || defined(TEST_SH_MATH)) |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 300 | /* round, divide, and either store or accumulate to output row */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 301 | acc = (acc + (1 << 21)) >> 22; |
| 302 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 303 | if (accum) |
| 304 | { |
| 305 | acc += out_line[ox]; |
| 306 | } |
| 307 | out_line[ox] = acc; |
| 308 | /* reset accumulator */ |
| 309 | acc = 0; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 310 | mul = oxe; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 311 | ox += 1; |
| 312 | /* inside an area */ |
| 313 | } else { |
| 314 | /* add pixel value to accumulator */ |
| 315 | acc += *(part->buf); |
| 316 | } |
| 317 | #endif |
| 318 | part->buf++; |
| 319 | part->len--; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 320 | } |
| 321 | return true; |
| 322 | } |
| 323 | |
| 324 | /* vertical area average scaler */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 325 | static inline bool scale_v_area(struct rowset *rset, struct scaler_context *ctx) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 326 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 327 | uint32_t mul, oy, iy, oye; |
| 328 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 329 | const uint32_t v_i_val = ctx->src->height, |
| 330 | v_o_val = ctx->bm->height; |
| 331 | #else |
| 332 | const uint32_t v_i_val = ctx->v_i_val, |
| 333 | v_o_val = ctx->v_o_val; |
| 334 | #endif |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 335 | |
| 336 | /* Set up rounding and scale factors */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 337 | mul = 0; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 338 | oy = rset->rowstart; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 339 | oye = 0; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 340 | #ifdef HAVE_LCD_COLOR |
| 341 | uint32_t *rowacc = (uint32_t *) ctx->buf, |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 342 | *rowtmp = rowacc + 3 * ctx->bm->width, |
| 343 | *rowacc_px, *rowtmp_px; |
Andrew Mahone | 07e982d | 2009-01-08 02:49:23 +0000 | [diff] [blame] | 344 | memset((void *)ctx->buf, 0, ctx->bm->width * 2 * sizeof(struct uint32_rgb)); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 345 | #else |
| 346 | uint32_t *rowacc = (uint32_t *) ctx->buf, |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 347 | *rowtmp = rowacc + ctx->bm->width, |
| 348 | *rowacc_px, *rowtmp_px; |
Andrew Mahone | 07e982d | 2009-01-08 02:49:23 +0000 | [diff] [blame] | 349 | memset((void *)ctx->buf, 0, ctx->bm->width * 2 * sizeof(uint32_t)); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 350 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 351 | SDEBUGF("scale_v_area\n"); |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 352 | /* zero the accumulator and temp rows */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 353 | for (iy = 0; iy < (unsigned int)ctx->src->height; iy++) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 354 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 355 | oye += v_o_val; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 356 | /* end of current area has been reached */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 357 | if (oye >= v_i_val) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 358 | { |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 359 | /* "reset" error, which now represents partial coverage of the next |
| 360 | row by the next area |
| 361 | */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 362 | oye -= v_i_val; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 363 | /* add stored partial row to accumulator */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 364 | for(rowacc_px = rowacc, rowtmp_px = rowtmp; rowacc_px != rowtmp; |
| 365 | rowacc_px++, rowtmp_px++) |
| 366 | *rowacc_px = *rowacc_px * v_o_val + *rowtmp_px * mul; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 367 | /* store new scaled row in temp row */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 368 | if(!ctx->h_scaler(rowtmp, ctx, false)) |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 369 | return false; |
| 370 | /* add partial coverage by new row to this area, then round and |
| 371 | scale to final value |
| 372 | */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 373 | mul = v_o_val - oye; |
| 374 | for(rowacc_px = rowacc, rowtmp_px = rowtmp; rowacc_px != rowtmp; |
| 375 | rowacc_px++, rowtmp_px++) |
| 376 | *rowacc_px += mul * *rowtmp_px; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 377 | ctx->output_row(oy, (void*)rowacc, ctx); |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 378 | /* clear accumulator row, store partial coverage for next row */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 379 | #ifdef HAVE_LCD_COLOR |
Andrew Mahone | 07e982d | 2009-01-08 02:49:23 +0000 | [diff] [blame] | 380 | memset((void *)rowacc, 0, ctx->bm->width * sizeof(uint32_t) * 3); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 381 | #else |
Andrew Mahone | 07e982d | 2009-01-08 02:49:23 +0000 | [diff] [blame] | 382 | memset((void *)rowacc, 0, ctx->bm->width * sizeof(uint32_t)); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 383 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 384 | mul = oye; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 385 | oy += rset->rowstep; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 386 | /* inside an area */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 387 | } else { |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 388 | /* accumulate new scaled row to rowacc */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 389 | if (!ctx->h_scaler(rowacc, ctx, true)) |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 390 | return false; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 391 | } |
| 392 | } |
| 393 | return true; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 394 | } |
| 395 | |
| 396 | #ifdef HAVE_UPSCALER |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 397 | /* horizontal linear scaler */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 398 | static bool scale_h_linear(void *out_line_ptr, struct scaler_context *ctx, |
| 399 | bool accum) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 400 | { |
| 401 | unsigned int ix, ox, ixe; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 402 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 403 | const uint32_t h_i_val = ctx->src->width - 1, |
| 404 | h_o_val = ctx->bm->width - 1; |
| 405 | #else |
| 406 | const uint32_t h_i_val = ctx->h_i_val, |
| 407 | h_o_val = ctx->h_o_val; |
| 408 | #endif |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 409 | /* type x = x is an ugly hack for hiding an unitialized data warning. The |
| 410 | values are conditionally initialized before use, but other values are |
| 411 | set such that this will occur before these are used. |
| 412 | */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 413 | #ifdef HAVE_LCD_COLOR |
| 414 | struct uint32_rgb rgbval=rgbval, rgbinc=rgbinc, |
| 415 | *out_line = (struct uint32_rgb*)out_line_ptr; |
| 416 | #else |
| 417 | uint32_t val=val, inc=inc, *out_line = (uint32_t*)out_line_ptr; |
| 418 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 419 | struct img_part *part; |
| 420 | SDEBUGF("scale_h_linear\n"); |
| 421 | FILL_BUF_INIT(part,ctx->store_part,ctx->args); |
| 422 | ix = 0; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 423 | /* The error is set so that values are initialized on the first pass. */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 424 | ixe = h_o_val; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 425 | /* give other tasks a chance to run */ |
Andrew Mahone | 07e982d | 2009-01-08 02:49:23 +0000 | [diff] [blame] | 426 | yield(); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 427 | for (ox = 0; ox < (uint32_t)ctx->bm->width; ox++) |
| 428 | { |
| 429 | #ifdef HAVE_LCD_COLOR |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 430 | if (ixe >= h_o_val) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 431 | { |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 432 | /* Store the new "current" pixel value in rgbval, and the color |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 433 | step value in rgbinc. |
| 434 | */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 435 | ixe -= h_o_val; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 436 | rgbinc.r = -(part->buf->red); |
| 437 | rgbinc.g = -(part->buf->green); |
| 438 | rgbinc.b = -(part->buf->blue); |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 439 | #if defined(CPU_COLDFIRE) |
| 440 | /* Coldfire EMAC math */ |
| 441 | MAC(part->buf->red, h_o_val, 0); |
| 442 | MAC(part->buf->green, h_o_val, 1); |
| 443 | MAC(part->buf->blue, h_o_val, 2); |
| 444 | #else |
| 445 | /* generic C math */ |
| 446 | rgbval.r = (part->buf->red) * h_o_val; |
| 447 | rgbval.g = (part->buf->green) * h_o_val; |
| 448 | rgbval.b = (part->buf->blue) * h_o_val; |
| 449 | #endif /* CPU */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 450 | ix += 1; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 451 | /* If this wasn't the last pixel, add the next one to rgbinc. */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 452 | if (LIKELY(ix < (uint32_t)ctx->src->width)) { |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 453 | part->buf++; |
| 454 | part->len--; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 455 | /* Fetch new pixels if needed */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 456 | FILL_BUF(part,ctx->store_part,ctx->args); |
| 457 | rgbinc.r += part->buf->red; |
| 458 | rgbinc.g += part->buf->green; |
| 459 | rgbinc.b += part->buf->blue; |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 460 | /* Add a partial step to rgbval, in this pixel isn't precisely |
| 461 | aligned with the new source pixel |
| 462 | */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 463 | #if defined(CPU_COLDFIRE) |
| 464 | /* Coldfire EMAC math */ |
| 465 | MAC(rgbinc.r, ixe, 0); |
| 466 | MAC(rgbinc.g, ixe, 1); |
| 467 | MAC(rgbinc.b, ixe, 2); |
| 468 | #else |
| 469 | /* generic C math */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 470 | rgbval.r += rgbinc.r * ixe; |
| 471 | rgbval.g += rgbinc.g * ixe; |
| 472 | rgbval.b += rgbinc.b * ixe; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 473 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 474 | } |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 475 | #if defined(CPU_COLDFIRE) |
| 476 | /* get final EMAC result out of ACC registers */ |
| 477 | MAC_OUT(rgbval.r, 0); |
| 478 | MAC_OUT(rgbval.g, 1); |
| 479 | MAC_OUT(rgbval.b, 2); |
| 480 | #endif |
| 481 | /* Now multiply the color increment to its proper value */ |
| 482 | rgbinc.r *= h_i_val; |
| 483 | rgbinc.g *= h_i_val; |
| 484 | rgbinc.b *= h_i_val; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 485 | } else { |
| 486 | rgbval.r += rgbinc.r; |
| 487 | rgbval.g += rgbinc.g; |
| 488 | rgbval.b += rgbinc.b; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 489 | } |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 490 | /* round and scale values, and accumulate or store to output */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 491 | if (accum) |
| 492 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 493 | out_line[ox].r += (rgbval.r + (1 << 21)) >> 22; |
| 494 | out_line[ox].g += (rgbval.g + (1 << 21)) >> 22; |
| 495 | out_line[ox].b += (rgbval.b + (1 << 21)) >> 22; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 496 | } else { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 497 | out_line[ox].r = (rgbval.r + (1 << 21)) >> 22; |
| 498 | out_line[ox].g = (rgbval.g + (1 << 21)) >> 22; |
| 499 | out_line[ox].b = (rgbval.b + (1 << 21)) >> 22; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 500 | } |
| 501 | #else |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 502 | if (ixe >= h_o_val) |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 503 | { |
| 504 | /* Store the new "current" pixel value in rgbval, and the color |
| 505 | step value in rgbinc. |
| 506 | */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 507 | ixe -= h_o_val; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 508 | val = *(part->buf); |
| 509 | inc = -val; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 510 | #if defined(CPU_COLDFIRE) |
| 511 | /* Coldfire EMAC math */ |
| 512 | MAC(val, h_o_val, 0); |
| 513 | #elif defined(CPU_SH) |
| 514 | /* SH-1 16x16->32 math */ |
| 515 | val = mul_u16_u16(val, h_o_val); |
| 516 | #else |
| 517 | /* generic C math */ |
| 518 | val = val * h_o_val; |
| 519 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 520 | ix += 1; |
| 521 | /* If this wasn't the last pixel, add the next one to rgbinc. */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 522 | if (LIKELY(ix < (uint32_t)ctx->src->width)) { |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 523 | part->buf++; |
| 524 | part->len--; |
| 525 | /* Fetch new pixels if needed */ |
| 526 | FILL_BUF(part,ctx->store_part,ctx->args); |
| 527 | inc += *(part->buf); |
| 528 | /* Add a partial step to rgbval, in this pixel isn't precisely |
| 529 | aligned with the new source pixel |
| 530 | */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 531 | #if defined(CPU_COLDFIRE) |
| 532 | /* Coldfire EMAC math */ |
| 533 | MAC(inc, ixe, 0); |
| 534 | #elif defined(CPU_SH) |
| 535 | /* SH-1 16x16->32 math */ |
| 536 | val += mul_s16_s16(inc, ixe); |
| 537 | #else |
| 538 | /* generic C math */ |
| 539 | val += inc * ixe; |
| 540 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 541 | } |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 542 | #if defined(CPU_COLDFIRE) |
| 543 | /* get final EMAC result out of ACC register */ |
| 544 | MAC_OUT(val, 0); |
| 545 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 546 | /* Now multiply the color increment to its proper value */ |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 547 | #if defined(CPU_SH) |
| 548 | /* SH-1 16x16->32 math */ |
| 549 | inc = mul_s16_s16(inc, h_i_val); |
| 550 | #else |
| 551 | /* generic C math */ |
| 552 | inc *= h_i_val; |
| 553 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 554 | } else |
| 555 | val += inc; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 556 | #if !(defined(CPU_SH) || defined(TEST_SH_MATH)) |
| 557 | /* round and scale values, and accumulate or store to output */ |
| 558 | if (accum) |
| 559 | { |
| 560 | out_line[ox] += (val + (1 << 21)) >> 22; |
| 561 | } else { |
| 562 | out_line[ox] = (val + (1 << 21)) >> 22; |
| 563 | } |
| 564 | #else |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 565 | /* round and scale values, and accumulate or store to output */ |
| 566 | if (accum) |
| 567 | { |
| 568 | out_line[ox] += val; |
| 569 | } else { |
| 570 | out_line[ox] = val; |
| 571 | } |
| 572 | #endif |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 573 | #endif |
| 574 | ixe += h_i_val; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 575 | } |
| 576 | return true; |
| 577 | } |
| 578 | |
| 579 | /* vertical linear scaler */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 580 | static inline bool scale_v_linear(struct rowset *rset, |
| 581 | struct scaler_context *ctx) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 582 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 583 | uint32_t mul, iy, iye; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 584 | int32_t oy; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 585 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 586 | const uint32_t v_i_val = ctx->src->height - 1, |
| 587 | v_o_val = ctx->bm->height - 1; |
| 588 | #else |
| 589 | const uint32_t v_i_val = ctx->v_i_val, |
| 590 | v_o_val = ctx->v_o_val; |
| 591 | #endif |
| 592 | /* Set up our buffers, to store the increment and current value for each |
| 593 | column, and one temp buffer used to read in new rows. |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 594 | */ |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 595 | #ifdef HAVE_LCD_COLOR |
| 596 | uint32_t *rowinc = (uint32_t *)(ctx->buf), |
| 597 | *rowval = rowinc + 3 * ctx->bm->width, |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 598 | *rowtmp = rowval + 3 * ctx->bm->width, |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 599 | #else |
| 600 | uint32_t *rowinc = (uint32_t *)(ctx->buf), |
| 601 | *rowval = rowinc + ctx->bm->width, |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 602 | *rowtmp = rowval + ctx->bm->width, |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 603 | #endif |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 604 | *rowinc_px, *rowval_px, *rowtmp_px; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 605 | |
| 606 | SDEBUGF("scale_v_linear\n"); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 607 | mul = 0; |
| 608 | iy = 0; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 609 | iye = v_o_val; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 610 | /* get first scaled row in rowtmp */ |
| 611 | if(!ctx->h_scaler((void*)rowtmp, ctx, false)) |
Andrew Mahone | 995c89c | 2008-12-10 12:09:03 +0000 | [diff] [blame] | 612 | return false; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 613 | for (oy = rset->rowstart; oy != rset->rowstop; oy += rset->rowstep) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 614 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 615 | if (iye >= v_o_val) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 616 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 617 | iye -= v_o_val; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 618 | iy += 1; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 619 | for(rowinc_px = rowinc, rowtmp_px = rowtmp, rowval_px = rowval; |
| 620 | rowinc_px < rowval; rowinc_px++, rowtmp_px++, rowval_px++) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 621 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 622 | *rowinc_px = -*rowtmp_px; |
| 623 | *rowval_px = *rowtmp_px * v_o_val; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 624 | } |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 625 | if (iy < (uint32_t)ctx->src->height) |
| 626 | { |
| 627 | if (!ctx->h_scaler((void*)rowtmp, ctx, false)) |
| 628 | return false; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 629 | for(rowinc_px = rowinc, rowtmp_px = rowtmp, rowval_px = rowval; |
| 630 | rowinc_px < rowval; rowinc_px++, rowtmp_px++, rowval_px++) |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 631 | { |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 632 | *rowinc_px += *rowtmp_px; |
| 633 | *rowval_px += *rowinc_px * iye; |
| 634 | *rowinc_px *= v_i_val; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 635 | } |
| 636 | } |
| 637 | } else |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 638 | for(rowinc_px = rowinc, rowval_px = rowval; rowinc_px < rowval; |
| 639 | rowinc_px++, rowval_px++) |
| 640 | *rowval_px += *rowinc_px; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 641 | ctx->output_row(oy, (void*)rowval, ctx); |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 642 | iye += v_i_val; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 643 | } |
| 644 | return true; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 645 | } |
| 646 | #endif /* HAVE_UPSCALER */ |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 647 | |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 648 | #if defined(HAVE_LCD_COLOR) && (defined(HAVE_JPEG) || defined(PLUGIN)) |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 649 | static void output_row_32_native_fromyuv(uint32_t row, void * row_in, |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 650 | struct scaler_context *ctx) |
| 651 | { |
| 652 | int col; |
| 653 | int fb_width = BM_WIDTH(ctx->bm->width,FORMAT_NATIVE,0); |
| 654 | uint8_t dy = DITHERY(row); |
| 655 | struct uint32_rgb *qp = (struct uint32_rgb *)row_in; |
| 656 | SDEBUGF("output_row: y: %lu in: %p\n",row, row_in); |
| 657 | fb_data *dest = (fb_data *)ctx->bm->data + fb_width * row; |
| 658 | int delta = 127; |
| 659 | unsigned r, g, b, y, u, v; |
| 660 | |
| 661 | for (col = 0; col < ctx->bm->width; col++) { |
| 662 | if (ctx->dither) |
| 663 | delta = DITHERXDY(col,dy); |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 664 | y = SC_OUT(qp->b, ctx); |
| 665 | u = SC_OUT(qp->g, ctx); |
| 666 | v = SC_OUT(qp->r, ctx); |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 667 | qp++; |
| 668 | yuv_to_rgb(y, u, v, &r, &g, &b); |
| 669 | r = (31 * r + (r >> 3) + delta) >> 8; |
| 670 | g = (63 * g + (g >> 2) + delta) >> 8; |
| 671 | b = (31 * b + (b >> 3) + delta) >> 8; |
| 672 | *dest++ = LCD_RGBPACK_LCD(r, g, b); |
| 673 | } |
| 674 | } |
| 675 | #endif |
| 676 | |
Andrew Mahone | 20f76d6 | 2009-05-04 15:46:41 +0000 | [diff] [blame] | 677 | #if !defined(PLUGIN) || LCD_DEPTH > 1 |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 678 | static void output_row_32_native(uint32_t row, void * row_in, |
Andrew Mahone | 20f76d6 | 2009-05-04 15:46:41 +0000 | [diff] [blame] | 679 | struct scaler_context *ctx) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 680 | { |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 681 | int col; |
| 682 | int fb_width = BM_WIDTH(ctx->bm->width,FORMAT_NATIVE,0); |
| 683 | uint8_t dy = DITHERY(row); |
| 684 | #ifdef HAVE_LCD_COLOR |
| 685 | struct uint32_rgb *qp = (struct uint32_rgb*)row_in; |
| 686 | #else |
| 687 | uint32_t *qp = (uint32_t*)row_in; |
| 688 | #endif |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 689 | SDEBUGF("output_row: y: %lu in: %p\n",row, row_in); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 690 | #if LCD_DEPTH == 2 |
| 691 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING |
| 692 | /* greyscale iPods */ |
| 693 | fb_data *dest = (fb_data *)ctx->bm->data + fb_width * row; |
| 694 | int shift = 6; |
| 695 | int delta = 127; |
| 696 | unsigned bright; |
| 697 | unsigned data = 0; |
| 698 | |
| 699 | for (col = 0; col < ctx->bm->width; col++) { |
| 700 | if (ctx->dither) |
| 701 | delta = DITHERXDY(col,dy); |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 702 | bright = SC_OUT(*qp++, ctx); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 703 | bright = (3 * bright + (bright >> 6) + delta) >> 8; |
| 704 | data |= (~bright & 3) << shift; |
| 705 | shift -= 2; |
| 706 | if (shift < 0) { |
| 707 | *dest++ = data; |
| 708 | data = 0; |
| 709 | shift = 6; |
| 710 | } |
| 711 | } |
| 712 | if (shift < 6) |
| 713 | *dest++ = data; |
| 714 | #elif LCD_PIXELFORMAT == VERTICAL_PACKING |
| 715 | /* iriver H1x0 */ |
| 716 | fb_data *dest = (fb_data *)ctx->bm->data + fb_width * |
| 717 | (row >> 2); |
| 718 | int shift = 2 * (row & 3); |
| 719 | int delta = 127; |
| 720 | unsigned bright; |
| 721 | |
| 722 | for (col = 0; col < ctx->bm->width; col++) { |
| 723 | if (ctx->dither) |
| 724 | delta = DITHERXDY(col,dy); |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 725 | bright = SC_OUT(*qp++, ctx); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 726 | bright = (3 * bright + (bright >> 6) + delta) >> 8; |
| 727 | *dest++ |= (~bright & 3) << shift; |
| 728 | } |
| 729 | #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED |
| 730 | /* iAudio M3 */ |
| 731 | fb_data *dest = (fb_data *)ctx->bm->data + fb_width * |
| 732 | (row >> 3); |
| 733 | int shift = row & 7; |
| 734 | int delta = 127; |
| 735 | unsigned bright; |
| 736 | |
| 737 | for (col = 0; col < ctx->bm->width; col++) { |
| 738 | if (ctx->dither) |
| 739 | delta = DITHERXDY(col,dy); |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 740 | bright = SC_OUT(*qp++, ctx); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 741 | bright = (3 * bright + (bright >> 6) + delta) >> 8; |
| 742 | *dest++ |= vi_pattern[bright] << shift; |
| 743 | } |
| 744 | #endif /* LCD_PIXELFORMAT */ |
| 745 | #elif LCD_DEPTH == 16 |
| 746 | /* iriver h300, colour iPods, X5 */ |
| 747 | fb_data *dest = (fb_data *)ctx->bm->data + fb_width * row; |
| 748 | int delta = 127; |
| 749 | unsigned r, g, b; |
| 750 | struct uint32_rgb q0; |
| 751 | |
| 752 | for (col = 0; col < ctx->bm->width; col++) { |
| 753 | if (ctx->dither) |
| 754 | delta = DITHERXDY(col,dy); |
| 755 | q0 = *qp++; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 756 | r = SC_OUT(q0.r, ctx); |
| 757 | g = SC_OUT(q0.g, ctx); |
| 758 | b = SC_OUT(q0.b, ctx); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 759 | r = (31 * r + (r >> 3) + delta) >> 8; |
| 760 | g = (63 * g + (g >> 2) + delta) >> 8; |
| 761 | b = (31 * b + (b >> 3) + delta) >> 8; |
| 762 | *dest++ = LCD_RGBPACK_LCD(r, g, b); |
| 763 | } |
| 764 | #endif /* LCD_DEPTH */ |
| 765 | } |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 766 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 767 | |
Andrew Mahone | 20f76d6 | 2009-05-04 15:46:41 +0000 | [diff] [blame] | 768 | #if defined(PLUGIN) && LCD_DEPTH > 1 |
| 769 | unsigned int get_size_native(struct bitmap *bm) |
| 770 | { |
Andrew Mahone | cda9074 | 2009-05-08 03:59:51 +0000 | [diff] [blame] | 771 | return BM_SIZE(bm->width,bm->height,FORMAT_NATIVE,0); |
Andrew Mahone | 20f76d6 | 2009-05-04 15:46:41 +0000 | [diff] [blame] | 772 | } |
| 773 | |
| 774 | const struct custom_format format_native = { |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 775 | .output_row_8 = output_row_8_native, |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 776 | #if defined(HAVE_LCD_COLOR) && (defined(HAVE_JPEG) || defined(PLUGIN)) |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 777 | .output_row_32 = { |
| 778 | output_row_32_native, |
| 779 | output_row_32_native_fromyuv |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 780 | }, |
| 781 | #else |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 782 | .output_row_32 = output_row_32_native, |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 783 | #endif |
Andrew Mahone | 20f76d6 | 2009-05-04 15:46:41 +0000 | [diff] [blame] | 784 | .get_size = get_size_native |
| 785 | }; |
| 786 | #endif |
| 787 | |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 788 | int resize_on_load(struct bitmap *bm, bool dither, struct dim *src, |
| 789 | struct rowset *rset, unsigned char *buf, unsigned int len, |
Andrew Mahone | 9058620 | 2008-12-26 07:05:13 +0000 | [diff] [blame] | 790 | const struct custom_format *format, |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 791 | IF_PIX_FMT(int format_index,) |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 792 | struct img_part* (*store_part)(void *args), |
| 793 | void *args) |
| 794 | { |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 795 | const int sw = src->width; |
| 796 | const int sh = src->height; |
| 797 | const int dw = bm->width; |
| 798 | const int dh = bm->height; |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 799 | int ret; |
| 800 | #ifdef HAVE_LCD_COLOR |
| 801 | unsigned int needed = sizeof(struct uint32_rgb) * 3 * bm->width; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 802 | #else |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 803 | unsigned int needed = sizeof(uint32_t) * 3 * bm->width; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 804 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 805 | #if MAX_SC_STACK_ALLOC |
| 806 | uint8_t sc_buf[(needed <= len || needed > MAX_SC_STACK_ALLOC) ? |
| 807 | 0 : needed]; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 808 | #endif |
Andrew Mahone | 2fbf097 | 2009-01-13 13:48:26 +0000 | [diff] [blame] | 809 | ALIGN_BUFFER(buf, len, sizeof(uint32_t)); |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 810 | if (needed > len) |
| 811 | { |
| 812 | #if MAX_SC_STACK_ALLOC |
| 813 | if (needed > MAX_SC_STACK_ALLOC) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 814 | { |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 815 | DEBUGF("unable to allocate required buffer: %d needed, " |
| 816 | "%d available, %d permitted from stack\n", |
| 817 | needed, len, MAX_SC_STACK_ALLOC); |
| 818 | return 0; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 819 | } |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 820 | if (sizeof(sc_buf) < needed) |
| 821 | { |
| 822 | DEBUGF("failed to allocate large enough buffer on stack: " |
| 823 | "%d needed, only got %d", |
| 824 | needed, MAX_SC_STACK_ALLOC); |
| 825 | return 0; |
| 826 | } |
| 827 | #else |
| 828 | DEBUGF("unable to allocate required buffer: %d needed, " |
| 829 | "%d available\n", needed, len); |
| 830 | return 0; |
| 831 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 832 | } |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 833 | |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 834 | struct scaler_context ctx; |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 835 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
Andrew Mahone | 07e982d | 2009-01-08 02:49:23 +0000 | [diff] [blame] | 836 | cpu_boost(true); |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 837 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 838 | ctx.store_part = store_part; |
| 839 | ctx.args = args; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 840 | #if MAX_SC_STACK_ALLOC |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 841 | ctx.buf = needed > len ? sc_buf : buf; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 842 | #else |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 843 | ctx.buf = buf; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 844 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 845 | ctx.len = len; |
| 846 | ctx.bm = bm; |
| 847 | ctx.src = src; |
| 848 | ctx.dither = dither; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 849 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 850 | uint32_t div; |
| 851 | #endif |
Andrew Mahone | 20f76d6 | 2009-05-04 15:46:41 +0000 | [diff] [blame] | 852 | #if !defined(PLUGIN) |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 853 | #if defined(HAVE_LCD_COLOR) && defined(HAVE_JPEG) |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 854 | ctx.output_row = format_index ? output_row_32_native_fromyuv |
| 855 | : output_row_32_native; |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 856 | #else |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 857 | ctx.output_row = output_row_32_native; |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 858 | #endif |
Andrew Mahone | 9058620 | 2008-12-26 07:05:13 +0000 | [diff] [blame] | 859 | if (format) |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 860 | #endif |
Andrew Mahone | 00d6cfd | 2009-05-26 20:26:05 +0000 | [diff] [blame] | 861 | #ifdef HAVE_LCD_COLOR |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 862 | ctx.output_row = format->output_row_32[format_index]; |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 863 | #else |
Andrew Mahone | 91efc16 | 2009-05-09 07:31:27 +0000 | [diff] [blame] | 864 | ctx.output_row = format->output_row_32; |
Andrew Mahone | eef7945 | 2009-05-06 04:53:56 +0000 | [diff] [blame] | 865 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 866 | #ifdef HAVE_UPSCALER |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 867 | if (sw > dw) |
| 868 | { |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 869 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 870 | ctx.h_scaler = scale_h_area; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 871 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 872 | div = sw; |
| 873 | #else |
| 874 | uint32_t h_div = (1U << 24) / sw; |
| 875 | ctx.h_i_val = sw * h_div; |
| 876 | ctx.h_o_val = dw * h_div; |
| 877 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 878 | #ifdef HAVE_UPSCALER |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 879 | } else { |
| 880 | ctx.h_scaler = scale_h_linear; |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 881 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 882 | div = dw - 1; |
| 883 | #else |
| 884 | uint32_t h_div = (1U << 24) / (dw - 1); |
| 885 | ctx.h_i_val = (sw - 1) * h_div; |
| 886 | ctx.h_o_val = (dw - 1) * h_div; |
| 887 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 888 | } |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 889 | #endif |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 890 | #ifdef CPU_COLDFIRE |
| 891 | coldfire_set_macsr(EMAC_UNSIGNED); |
| 892 | #endif |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 893 | #ifdef HAVE_UPSCALER |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 894 | if (sh > dh) |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 895 | #endif |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 896 | { |
| 897 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 898 | div *= sh; |
| 899 | ctx.recip = ((uint32_t)(-div)) / div + 1; |
| 900 | #else |
| 901 | uint32_t v_div = (1U << 22) / sh; |
| 902 | ctx.v_i_val = sh * v_div; |
| 903 | ctx.v_o_val = dh * v_div; |
| 904 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 905 | ret = scale_v_area(rset, &ctx); |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 906 | } |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 907 | #ifdef HAVE_UPSCALER |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 908 | else |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 909 | { |
| 910 | #if defined(CPU_SH) || defined (TEST_SH_MATH) |
| 911 | div *= dh - 1; |
| 912 | ctx.recip = ((uint32_t)(-div)) / div + 1; |
| 913 | #else |
| 914 | uint32_t v_div = (1U << 22) / dh; |
| 915 | ctx.v_i_val = (sh - 1) * v_div; |
| 916 | ctx.v_o_val = (dh - 1) * v_div; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 917 | #endif |
Andrew Mahone | 92785b8 | 2009-05-26 20:00:47 +0000 | [diff] [blame] | 918 | ret = scale_v_linear(rset, &ctx); |
| 919 | } |
| 920 | #endif |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 921 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
Andrew Mahone | 07e982d | 2009-01-08 02:49:23 +0000 | [diff] [blame] | 922 | cpu_boost(false); |
Andrew Mahone | 4eedc93 | 2009-01-04 21:22:05 +0000 | [diff] [blame] | 923 | #endif |
Andrew Mahone | f7fa7e5 | 2008-12-26 07:03:22 +0000 | [diff] [blame] | 924 | if (!ret) |
| 925 | return 0; |
Andrew Mahone | 9058620 | 2008-12-26 07:05:13 +0000 | [diff] [blame] | 926 | return 1; |
Andrew Mahone | 781421a | 2008-12-09 23:07:59 +0000 | [diff] [blame] | 927 | } |