overlay: support 2 V4L2 overlay devices
authoryuyeon.oh <yuyeon.oh@samsung.com>
Fri, 24 Jun 2011 08:24:30 +0000 (17:24 +0900)
committeryuyeon.oh <yuyeon.oh@samsung.com>
Fri, 24 Jun 2011 08:24:30 +0000 (17:24 +0900)
Change-Id: I865b70233fc08c573907b37bb5d8117e5b3ef392

hw/overlay.c
hw/vga.c

index 140d37d..a86a481 100755 (executable)
 #define PCI_VENDOR_ID_SAMSUNG          0x144d
 #define PCI_DEVICE_ID_VIRTUAL_OVERLAY   0x1010
 
-#define OVERLAY_MEM_SIZE (8192 * 1024) // 4MB(overlay0) + 4MB(overlay1)
-#define OVERLAY_REG_SIZE 256
+#define OVERLAY_MEM_SIZE       (8192 * 1024)   // 4MB(overlay0) + 4MB(overlay1)
+#define OVERLAY_REG_SIZE       256
+#define OVERLAY1_REG_OFFSET    (OVERLAY_REG_SIZE / 2)
+
 
 enum {
-    OVERLAY0_POWER    = 0x00,
-    OVERLAY0_SIZE     = 0x04,  // width and height
-    OVERLAY0_POSITION = 0x08,  // left top position
-    OVERLAY1_POWER    = 0x0C,
-    OVERLAY1_SIZE     = 0x10,  // width and height
-    OVERLAY1_POSITION = 0x14,  // left top position
+       OVERLAY_POWER    = 0x00,
+       OVERLAY_POSITION = 0x04,        // left top position
+       OVERLAY_SIZE     = 0x08,        // width and height
 };
 
-uint32_t overlay0_power;
-uint32_t overlay0_size;
-uint32_t overlay0_position;
-uint32_t overlay1_power;
-uint32_t overlay1_size;
-uint32_t overlay1_position;
+uint8_t overlay0_power;
+uint16_t overlay0_left;
+uint16_t overlay0_top;
+uint16_t overlay0_width;
+uint16_t overlay0_height;
+
+uint8_t overlay1_power;
+uint16_t overlay1_left;
+uint16_t overlay1_top;
+uint16_t overlay1_width;
+uint16_t overlay1_height;
 
 uint8_t* overlay_ptr;  // pointer in qemu space
 
@@ -57,51 +61,56 @@ typedef struct OverlayState {
 static uint32_t overlay_reg_read(void *opaque, target_phys_addr_t addr)
 {
     switch (addr) {
-    case OVERLAY0_POWER:
+    case OVERLAY_POWER:
         return overlay0_power;
         break;
-    case OVERLAY0_SIZE:
-        return overlay0_size;
+    case OVERLAY_SIZE:
+        return overlay0_left | overlay0_top << 16;
         break;
-    case OVERLAY0_POSITION:
-        return overlay0_position;
+    case OVERLAY_POSITION:
+        return overlay0_width | overlay0_height << 16;
         break;
-    case OVERLAY1_POWER:
+    case OVERLAY1_REG_OFFSET + OVERLAY_POWER:
         return overlay1_power;
         break;
-    case OVERLAY1_SIZE:
-        return overlay1_size;
+    case OVERLAY1_REG_OFFSET + OVERLAY_SIZE:
+        return overlay1_left | overlay1_top << 16;
         break;
-    case OVERLAY1_POSITION:
-        return overlay1_position;
+    case OVERLAY1_REG_OFFSET + OVERLAY_POSITION:
+        return overlay1_width | overlay1_height << 16;
         break;
     default:
         fprintf(stderr, "wrong overlay register read - addr : %d\n", addr);
     }
 
+
     return 0;
 }
 
 static void overlay_reg_write(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     switch (addr) {
-    case OVERLAY0_POWER:
+    case OVERLAY_POWER:
         overlay0_power = val;
         break;
-    case OVERLAY0_SIZE:
-        overlay0_size = val;
+    case OVERLAY_SIZE:
+        overlay0_left = val & 0xFFFF;
+        overlay0_top = val >> 16;
         break;
-    case OVERLAY0_POSITION:
-        overlay0_position = val;
+    case OVERLAY_POSITION:
+        overlay0_width = val & 0xFFFF;
+        overlay0_height = val >> 16;
         break;
-    case OVERLAY1_POWER:
+    case OVERLAY1_REG_OFFSET + OVERLAY_POWER:
         overlay1_power = val;
         break;
-    case OVERLAY1_SIZE:
-        overlay1_size = val;
+    case OVERLAY1_REG_OFFSET + OVERLAY_SIZE:
+        overlay1_left = val & 0xFFFF;
+        overlay1_top = val >> 16;
         break;
-    case OVERLAY1_POSITION:
-        overlay1_position = val;
+    case OVERLAY1_REG_OFFSET + OVERLAY_POSITION:
+        overlay1_width = val & 0xFFFF;
+        overlay1_height = val >> 16;
         break;
     default:
         fprintf(stderr, "wrong overlay register write - addr : %d\n", addr);
index 32e4328..e123810 100755 (executable)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1614,13 +1614,18 @@ void vga_dirty_log_restart(VGACommonState *s)
 /*
 * graphic modes
 */
-extern uint32_t overlay0_power;
-extern uint32_t overlay0_size;
-extern uint32_t overlay0_position;
-extern uint32_t overlay1_power;
-extern uint32_t overlay1_size;
-extern uint32_t overlay1_position;
-
+extern uint8_t overlay0_power;
+extern uint16_t overlay0_left;
+extern uint16_t overlay0_top;
+extern uint16_t overlay0_width;
+extern uint16_t overlay0_height;
+       
+extern uint8_t overlay1_power;
+extern uint16_t overlay1_left;
+extern uint16_t overlay1_top;
+extern uint16_t overlay1_width;
+extern uint16_t overlay1_height;
+       
 extern uint8_t* overlay_ptr;   // pointer in qemu space
 
 static void vga_draw_graphic(VGACommonState *s, int full_update)
@@ -1799,28 +1804,56 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
                 page_min = page0;
             if (page1 > page_max)
                 page_max = page1;
+            if (!(is_buffer_shared(s->ds->surface))) {
+                vga_draw_line(s, d, s->vram_ptr + addr, width);
+           }
+           
+           int i;
+           uint8_t *fb_sub;
+           uint8_t *over_sub;
+           uint8_t alpha, c_alpha;
+           uint32_t *dst;
+           uint16_t overlay_bottom;
+
             if (overlay0_power) {
-                int i;
-               uint8_t *fb_sub= s->vram_ptr + addr;
-               uint8_t *over_sub = overlay_ptr + addr;
-               uint8_t alpha, c_alpha;
-               uint32_t *dst = (uint32_t*)(s->ds->surface->data + addr);
-
-                for (i = 0; i < width; i++, fb_sub += 4, over_sub += 4, dst++) {
-                    alpha = fb_sub[3];
-                    c_alpha = 0xff - alpha;
-                    //fprintf(stderr, "alpha = %d\n", alpha);
-                    
-                    *dst = ((c_alpha * over_sub[0] + alpha * fb_sub[0]) >> 8) |
-                           ((c_alpha * over_sub[1] + alpha * fb_sub[1]) & 0xFF00) |
-                           ((c_alpha * over_sub[2] + alpha * fb_sub[2]) & 0xFF00) << 8;
+                overlay_bottom = overlay0_top + overlay0_height;
+
+                if (overlay0_top <= y && y < overlay_bottom) {
+                    fb_sub= s->vram_ptr + addr + overlay0_left;
+                    over_sub = overlay_ptr + y * overlay0_width;
+                    dst = (uint32_t*)(s->ds->surface->data + addr + overlay0_left);
+    
+                    for (i = 0; i < overlay0_width; i++, fb_sub += 4, over_sub += 4, dst++) {
+                        alpha = fb_sub[3];
+                        c_alpha = 0xff - alpha;
+                        //fprintf(stderr, "alpha = %d\n", alpha);
+                        
+                        *dst = ((c_alpha * over_sub[0] + alpha * fb_sub[0]) >> 8) |
+                               ((c_alpha * over_sub[1] + alpha * fb_sub[1]) & 0xFF00) |
+                               ((c_alpha * over_sub[2] + alpha * fb_sub[2]) & 0xFF00) << 8;
+                    }
+                }
+            }
+
+            if (overlay1_power) {
+                overlay_bottom = overlay1_top + overlay1_height;
+
+                if (overlay1_top <= y && y < overlay_bottom) {
+                    fb_sub= s->vram_ptr + addr + overlay1_left;
+                    over_sub = overlay_ptr + 0x400000 + y * overlay1_width;            // 4MB apart
+                    dst = (uint32_t*)(s->ds->surface->data + addr + overlay1_left);
+    
+                    for (i = 0; i < overlay0_width; i++, fb_sub += 4, over_sub += 4, dst++) {
+                        alpha = fb_sub[3];
+                        c_alpha = 0xff - alpha;
+                        //fprintf(stderr, "alpha = %d\n", alpha);
+                        
+                        *dst = ((c_alpha * over_sub[0] + alpha * fb_sub[0]) >> 8) |
+                               ((c_alpha * over_sub[1] + alpha * fb_sub[1]) & 0xFF00) |
+                               ((c_alpha * over_sub[2] + alpha * fb_sub[2]) & 0xFF00) << 8;
+                    }
                 }
             }
-            else  if (!(is_buffer_shared(s->ds->surface))) {
-                vga_draw_line(s, d, s->vram_ptr + addr, width);
-                if (s->cursor_draw_line)
-                    s->cursor_draw_line(s, d, y);
-           }
         } else {
             if (y_start >= 0) {
                 /* flush to display */