guilib.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * guilib - a minimal pixel framework
  3. *
  4. * Copyright (c) 2009 Openmoko Inc.
  5. *
  6. * Authors Daniel Mack <daniel@caiaq.de>
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include <file-io.h>
  22. #include <msg.h>
  23. #include <string.h>
  24. #include "guilib.h"
  25. #include "glyph.h"
  26. #include <regs.h>
  27. #include <lcd.h>
  28. #include <samo.h>
  29. // just redfine, fix later
  30. #define FRAMEBUFFER_WIDTH LCD_WIDTH_PIXELS
  31. #define FRAMEBUFFER_HEIGHT LCD_HEIGHT_LINES
  32. #define FRAMEBUFFER_SCANLINE LCD_VRAM_WIDTH_PIXELS
  33. #define FRAMEBUFFER_SIZE LCD_VRAM_SIZE
  34. #define EXTRACT_PIXEL(x, y) \
  35. unsigned int byte = (x + FRAMEBUFFER_SCANLINE * y) / 8; \
  36. unsigned int bit = (x + FRAMEBUFFER_SCANLINE * y) % 8; \
  37. \
  38. if (byte >= FRAMEBUFFER_SIZE) \
  39. return;
  40. unsigned int guilib_framebuffer_width(void)
  41. {
  42. return FRAMEBUFFER_WIDTH;
  43. }
  44. unsigned int guilib_framebuffer_height(void)
  45. {
  46. return FRAMEBUFFER_HEIGHT;
  47. }
  48. unsigned int guilib_framebuffer_size(void)
  49. {
  50. return FRAMEBUFFER_SIZE;
  51. }
  52. /*
  53. * Special version for really setting the pixel as it
  54. * should be... This does not take DISPLAY_INVERTED into
  55. * account.
  56. */
  57. static void guilib_set_pixel_plain(int x, int y, int v)
  58. {
  59. EXTRACT_PIXEL(x, y)
  60. if (v)
  61. framebuffer[byte] |= 0x80 >> bit;
  62. else
  63. framebuffer[byte] &= ~(0x80 >> bit);
  64. }
  65. void guilib_set_pixel(int x, int y, int v)
  66. {
  67. EXTRACT_PIXEL(x, y)
  68. if (v)
  69. #ifdef DISPLAY_INVERTED
  70. framebuffer[byte] &= ~(1 << (7 - bit));
  71. else
  72. framebuffer[byte] |= (1 << (7 - bit));
  73. #else
  74. framebuffer[byte] |= (1 << (7 - bit));
  75. else
  76. framebuffer[byte] &= ~(1 << (7 - bit));
  77. #endif
  78. }
  79. int guilib_get_pixel(int x, int y)
  80. {
  81. unsigned int byte = (x + FRAMEBUFFER_SCANLINE * y) / 8;
  82. unsigned int bit = (x + FRAMEBUFFER_SCANLINE * y) % 8;
  83. int bit_set = (framebuffer[byte] & 0x80>>bit) != 0;
  84. #ifdef DISPLAY_INVERTED
  85. bit_set = !bit_set;
  86. #endif
  87. return bit_set;
  88. }
  89. /**
  90. * Invert the pixels of lines starting at @param start_line
  91. * and the following @param height lines.
  92. */
  93. void guilib_invert(int start_line, int height)
  94. {
  95. int x, y;
  96. for (y = 0; y < height; ++y) {
  97. for (x = 0; x < FRAMEBUFFER_SCANLINE; x += 8) {
  98. unsigned int byte = (x + FRAMEBUFFER_SCANLINE * (start_line + y)) / 8;
  99. framebuffer[byte] = ~framebuffer[byte];
  100. }
  101. }
  102. }
  103. /**
  104. * Invert the area specified on the screen.
  105. */
  106. void guilib_invert_area(unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y)
  107. {
  108. unsigned int x, y;
  109. for (y = start_y; y <= end_y; ++y) {
  110. for (x = start_x; x <= end_x; x++) {
  111. unsigned int pixel = guilib_get_pixel(x, y);
  112. guilib_set_pixel_plain(x, y, !pixel);
  113. }
  114. }
  115. }
  116. /**
  117. * Clear the content of the screen.
  118. */
  119. void guilib_clear(void)
  120. {
  121. #ifdef DISPLAY_INVERTED
  122. memset(framebuffer, ~0, FRAMEBUFFER_SIZE);
  123. #else
  124. memset(framebuffer, 0, FRAMEBUFFER_SIZE);
  125. #endif
  126. }
  127. /**
  128. * Clear the area specified on the screen.
  129. */
  130. void guilib_clear_area(unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y)
  131. {
  132. unsigned int x, y;
  133. for (y = start_y; y <= end_y; ++y) {
  134. for (x = start_x; x <= end_x; x++)
  135. #ifdef DISPLAY_INVERTE
  136. guilib_set_pixel_plain(x, y, 1);
  137. #else
  138. guilib_set_pixel_plain(x, y, 0);
  139. #endif
  140. }
  141. }
  142. /* The idea is that every function which calls painting routines calls
  143. * guilib_fb_lock() before any operation and guilib_fb_unlock() after
  144. * it. This way, only the last of these functions in the calling stack
  145. * will actually execute fb_refresh(). */
  146. static int fb_ref = 0;
  147. void guilib_fb_lock(void)
  148. {
  149. fb_ref++;
  150. }
  151. void guilib_fb_unlock(void)
  152. {
  153. if (fb_ref == 0)
  154. return;
  155. if (--fb_ref == 0)
  156. fb_refresh();
  157. }
  158. #define IMG_GET_PIXEL(img,x,y) \
  159. (img->data[(x + img->width * y) / 8] >> (7 - (x + img->width * y) % 8) & 1)
  160. void guilib_blit_image(const struct guilib_image *img, int x, int y)
  161. {
  162. unsigned int xx, yy;
  163. /* special case: the image has the same width than the
  164. * height and is rendered at y=0. Then we can go for a
  165. * simple memcpy() */
  166. if (y == 0 && img->width == FRAMEBUFFER_SCANLINE) {
  167. memcpy(framebuffer + (x + FRAMEBUFFER_SCANLINE * y) / 8,
  168. img->data, (img->width * img->height) / 8);
  169. return;
  170. }
  171. /* special case: the image will be blitted byte aligned.
  172. * we can simply copy over all the bytes, without bit
  173. * fiddling. We can copy it line by line*/
  174. if ((x & 7) == 0 && img->width == FRAMEBUFFER_WIDTH) {
  175. unsigned int i;
  176. for (i = 0; i < img->height; ++i) {
  177. unsigned char *d = framebuffer + (x + FRAMEBUFFER_SCANLINE * (y+i)) / 8;
  178. memcpy(d, &img->data[(i*img->width) / 8], img->width / 8);
  179. }
  180. return;
  181. }
  182. /* hardest case - go for bit fiddling */
  183. for (xx = 0; xx < img->width; xx++)
  184. for (yy = 0; yy < img->height; yy++)
  185. guilib_set_pixel_plain(x + xx, y + yy,
  186. IMG_GET_PIXEL(img, xx, yy));
  187. }
  188. void guilib_init(void)
  189. {
  190. guilib_clear();
  191. }