video graphics test : new demo application
authorManisha Agrawal <manisha.agrawal@ti.com>
Mon, 19 Feb 2018 22:02:58 +0000 (16:02 -0600)
committerManisha Agrawal <manisha.agrawal@ti.com>
Mon, 19 Feb 2018 22:02:58 +0000 (16:02 -0600)
 This is completly new application sharing the same name video
 graphcis test. The previous demo application will no longer be
 supported.
 eglf_kms QT QPA API has been enhanced to support multiple display and
 advance Display subsystem capabilities like scaling, aplhablending and
 overlaying. This  application demonstartes -
 1. New  enhanced QT eglfs_kms QPA capabilties
 2. Dual screen display using eglfs_kms
 3. Two different graphics content on two screen using QT QML drawning on SGX
 4. 90 degree rotation using GC320
 5. Two different video source on two screens - one from VIP capture and
 other from GC320  90 degree rotated content.

 dual screen display for graphics content drawn using QT QML annd user
 overlay planes from camera source and GC320 rotation.

Signed-off-by: Manisha Agrawal <manisha.agrawal@ti.com>
101 files changed:
capture.cpp [new file with mode: 0755]
capture.h [new file with mode: 0755]
clocks.qml [new file with mode: 0755]
cmem_buf.cpp [new file with mode: 0755]
cmem_buf.h [new file with mode: 0755]
content/BuildButton.qml [new file with mode: 0755]
content/Clock.qml [new file with mode: 0755]
content/GameCanvas.qml [new file with mode: 0755]
content/GameOverScreen.qml [new file with mode: 0755]
content/InfoBar.qml [new file with mode: 0755]
content/NewGameScreen.qml [new file with mode: 0755]
content/SoundEffect.qml [new file with mode: 0755]
content/arrow.png [new file with mode: 0755]
content/audio/bomb-action.wav [new file with mode: 0755]
content/audio/catch-action.wav [new file with mode: 0755]
content/audio/catch.wav [new file with mode: 0755]
content/audio/currency.wav [new file with mode: 0755]
content/audio/factory-action.wav [new file with mode: 0755]
content/audio/melee-action.wav [new file with mode: 0755]
content/audio/projectile-action.wav [new file with mode: 0755]
content/audio/shooter-action.wav [new file with mode: 0755]
content/background.png [new file with mode: 0755]
content/center.png [new file with mode: 0755]
content/clock-night.png [new file with mode: 0755]
content/clock.png [new file with mode: 0644]
content/gfx/background.png [new file with mode: 0755]
content/gfx/bomb-action.png [new file with mode: 0755]
content/gfx/bomb-idle.png [new file with mode: 0755]
content/gfx/bomb.png [new file with mode: 0755]
content/gfx/button-help.png [new file with mode: 0755]
content/gfx/button-play.png [new file with mode: 0755]
content/gfx/catch-action.png [new file with mode: 0755]
content/gfx/catch.png [new file with mode: 0755]
content/gfx/cloud.png [new file with mode: 0755]
content/gfx/currency.png [new file with mode: 0755]
content/gfx/dialog-bomb.png [new file with mode: 0755]
content/gfx/dialog-factory.png [new file with mode: 0755]
content/gfx/dialog-melee.png [new file with mode: 0755]
content/gfx/dialog-pointer.png [new file with mode: 0755]
content/gfx/dialog-shooter.png [new file with mode: 0755]
content/gfx/dialog.png [new file with mode: 0755]
content/gfx/factory-action.png [new file with mode: 0755]
content/gfx/factory-idle.png [new file with mode: 0755]
content/gfx/factory.png [new file with mode: 0755]
content/gfx/grid.png [new file with mode: 0755]
content/gfx/help.png [new file with mode: 0755]
content/gfx/lifes.png [new file with mode: 0755]
content/gfx/logo-bubble.png [new file with mode: 0755]
content/gfx/logo-fish.png [new file with mode: 0755]
content/gfx/logo.png [new file with mode: 0755]
content/gfx/melee-action.png [new file with mode: 0755]
content/gfx/melee-idle.png [new file with mode: 0755]
content/gfx/melee.png [new file with mode: 0755]
content/gfx/mob-idle.png [new file with mode: 0755]
content/gfx/mob.png [new file with mode: 0755]
content/gfx/points.png [new file with mode: 0755]
content/gfx/projectile-action.png [new file with mode: 0755]
content/gfx/projectile.png [new file with mode: 0755]
content/gfx/scores.png [new file with mode: 0755]
content/gfx/shooter-action.png [new file with mode: 0755]
content/gfx/shooter-idle.png [new file with mode: 0755]
content/gfx/shooter.png [new file with mode: 0755]
content/gfx/sunlight.png [new file with mode: 0755]
content/gfx/text-1.png [new file with mode: 0755]
content/gfx/text-2.png [new file with mode: 0755]
content/gfx/text-3.png [new file with mode: 0755]
content/gfx/text-blank.png [new file with mode: 0755]
content/gfx/text-gameover.png [new file with mode: 0755]
content/gfx/text-go.png [new file with mode: 0755]
content/gfx/wave.png [new file with mode: 0755]
content/hour.png [new file with mode: 0755]
content/logic.js [new file with mode: 0755]
content/minute.png [new file with mode: 0755]
content/mobs/MobBase.qml [new file with mode: 0755]
content/quit.png [new file with mode: 0755]
content/second.png [new file with mode: 0755]
content/towers/Bomb.qml [new file with mode: 0755]
content/towers/Factory.qml [new file with mode: 0755]
content/towers/Melee.qml [new file with mode: 0755]
content/towers/Ranged.qml [new file with mode: 0755]
content/towers/TowerBase.qml [new file with mode: 0755]
disp_obj.cpp [new file with mode: 0755]
disp_obj.h [new file with mode: 0755]
error.h [new file with mode: 0755]
gc320.cpp [new file with mode: 0755]
gc320.h [new file with mode: 0755]
loopback.c [deleted file]
loopback.h [deleted file]
main.cpp
mainwindow.cpp [deleted file]
mainwindow.h [deleted file]
mainwindow.ui [deleted file]
maroon.qml [new file with mode: 0755]
qpa_ctl.cpp [new file with mode: 0755]
qpa_ctl.h [new file with mode: 0755]
v4l2_obj.cpp [new file with mode: 0755]
v4l2_obj.h [new file with mode: 0755]
video_graphics_test.cpp [new file with mode: 0755]
video_graphics_test.h [new file with mode: 0755]
video_graphics_test.pro
video_graphics_test.qrc [new file with mode: 0644]

diff --git a/capture.cpp b/capture.cpp
new file mode 100755 (executable)
index 0000000..ee34469
--- /dev/null
@@ -0,0 +1,297 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <malloc.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stdbool.h>
+#include <linux/videodev2.h>
+
+#define NBUF (3)
+#define CAP_WIDTH 800
+#define CAP_HEIGHT 600
+
+
+
+/*
+* V4L2 capture device structure declaration
+*/
+class V4l2Obj {
+public: 
+       V4l2Obj();
+       V4l2Obj(const char * dev_name, int w, int h, int num_buf);
+   ~V4l2Obj();
+    int request_buf(int *fd);
+    int queue_buf(int fd);
+    int dequeue_buf();
+private:
+       int m_fd;
+       enum v4l2_memory m_memory_mode;
+       unsigned int num_buffers;
+       int m_width;
+       int m_height;
+       char m_dev_name[256];
+       struct v4l2_buffer *m_v4l2buf;
+       struct v4l2_format m_fmt;
+
+       void default_parameters();
+       void device_init();
+};
+
+/*
+* Initialize the app resources with default parameters
+*/
+void V4l2Obj::default_parameters(void)
+{
+       /* Main camera */
+       m_memory_mode = V4L2_MEMORY_DMABUF;
+       m_num_buffers = NBUF;
+       strcpy(m_dev_name,"/dev/video1");
+       m_buffers = NULL;
+    m_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+       m_width = CAP_WIDTH;
+       m_height = CAP_HEIGHT;
+
+       return;
+}
+
+void V4l2Obj::device_init()
+{
+               /* Open the capture device */
+       m_fd = open(m_dev_name, O_RDWR);
+       if (m_fd <= 0) {
+               printf("Cannot open %s device\n", m_dev_name);
+               return -1;
+       }
+
+       MSG("\n%s: Opened Channel\n", m_dev_name);
+
+       /* Check if the device is capable of streaming */
+       if (ioctl(m_fd, VIDIOC_QUERYCAP, &capability) < 0) {
+               perror("VIDIOC_QUERYCAP");
+               goto ERROR;
+       }
+
+       if (capability.capabilities & V4L2_CAP_STREAMING)
+               MSG("%s: Capable of streaming\n", m_dev_name);
+       else {
+               ERROR("%s: Not capable of streaming\n", m_dev_name);
+               goto ERROR;
+       }
+
+       streamparam.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       if (ioctl(m_fd, VIDIOC_G_PARM, &streamparam) < 0){
+               perror("VIDIOC_G_PARM");
+               goto ERROR;
+       }
+
+       m_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       ret = ioctl(m_fd, VIDIOC_G_FMT, &m_fmt);
+       if (ret < 0) {
+               ERROR("VIDIOC_G_FMT failed: %s (%d)", strerror(errno), ret);
+               goto ERROR;
+       }
+
+       m_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       m_fmt.fmt.pix.width = m_width;
+       m_fmt.fmt.pix.height = m_height;
+
+       ret = ioctl(m_fd, VIDIOC_S_FMT, &m_fmt);
+       if (ret < 0) {
+               perror("VIDIOC_S_FMT");
+               goto ERROR;
+       }
+
+       MSG("%s: Init done successfully\n", dev_name);
+
+ERROR:
+       close(m_fd);
+}
+
+V4l2Obj::V4l2Obj()
+{
+       int ret;
+       struct v4l2_capability capability;
+       struct v4l2_streamparm streamparam;
+
+       default_parameters();
+       v4l2_device_init();
+}
+
+V4l2Obj::V4l2Obj(const char * dev_name, int w, int h, int num_buf, int pix_fmt)
+{
+       int ret;
+       struct v4l2_capability capability;
+       struct v4l2_streamparm streamparam;
+
+       default_parameters();
+
+    m_dev_name = dev_name;
+       m_width = w;
+       m_height = h;
+       m_num_buffers = num_buf;
+    m_fmt.fmt.pix.pixelformat = pix_fmt;
+
+       v4l2_device_init();
+}
+
+V4l2Obj::~V4l2Obj(struct v4l2_device_info *device)
+{
+
+       free(m_v4l2buf);
+       close(m_fd);
+
+       return;
+}
+
+int V4l2Obj::request_buf(int *fd)
+{
+       struct v4l2_requestbuffers reqbuf;
+       unsigned int i;
+       int ret;
+
+       if (m_v4l2buf) {
+               // maybe eventually need to support this?
+               ERROR("already reqbuf'd");
+               return -1;
+       }
+
+       reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       reqbuf.memory = m_memory_mode;
+       reqbuf.count = m_num_buffers;
+
+       ret = ioctl(m_fd, VIDIOC_REQBUFS, &reqbuf);
+       if (ret < 0) {
+               ERROR("VIDIOC_REQBUFS failed: %s (%d)", strerror(errno), ret);
+               return ret;
+       }
+
+       if ((reqbuf.count != device->num_buffers) ||
+               (reqbuf.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+               (reqbuf.memory != V4L2_MEMORY_DMABUF)) {
+                       ERROR("unsupported..");
+                       return -1;
+       }
+
+       m_num_buffers = reqbuf.count;
+       m_v4l2buf = (struct v4l2_buffer *) calloc(m_num_buffers, \
+               sizeof(struct v4l2_buffer));
+       if (!m_v4l2buf) {
+               ERROR("allocation failed");
+               return -1;
+       }
+
+       for (i = 0; i < m_num_buffers; i++) {
+               m_v4l2buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               m_v4l2buf[i].memory = V4L2_MEMORY_DMABUF;
+               m_v4l2buf[i].index = i;
+
+               ret = ioctl(m_fd, VIDIOC_QUERYBUF, &m_v4l2buf[i]);
+               m_v4l2buf[i].m.fd = fd[i];
+
+               if (ret) {
+                       ERROR("VIDIOC_QUERYBUF failed: %s (%d)", strerror(errno), ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+/*
+* Queue V4L2 buffer
+*/
+int V4l2Obj::queue_buf(int fd)
+{
+       struct v4l2_buffer *v4l2buf = NULL;
+       int  ret;
+       unsigned char i;
+
+       if(buf->nbo != 1){
+               ERROR("number of bufers not right\n");
+               return -1;
+       }
+
+       for (i = 0; i < device->num_buffers; i++) {
+               if (m_v4l2buf[i].m.fd == fd) {
+                       v4l2buf = &m_v4l2buf[i];
+               }
+       }
+
+       if (!v4l2buf) {
+               ERROR("invalid buffer");
+               return -1;
+       }
+       ret = ioctl(m_fd, VIDIOC_QBUF, v4l2buf);
+       if (ret) {
+               ERROR("VIDIOC_QBUF failed: %s (%d)", strerror(errno), ret);
+       }
+
+       return ret;
+}
+
+/*
+* DeQueue V4L2 buffer
+*/
+int V4l2Obj::dequeue_buf()
+{
+       struct dmabuf_buffer *buf;
+       struct v4l2_buffer v4l2buf;
+       int ret;
+
+       v4l2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       v4l2buf.memory = V4L2_MEMORY_DMABUF;
+       ret = ioctl(m_fd, VIDIOC_DQBUF, &v4l2buf);
+       if (ret) {
+               ERROR("VIDIOC_DQBUF failed: %s (%d)\n", strerror(errno), ret);
+               return NULL;
+       }
+
+       m_v4l2buf[v4l2buf.index].timestamp = v4l2buf.timestamp;
+
+       return v4l2buf.index;
+}
+
+
+
+
+/*
+* Enable streaming for V4L2 capture device
+*/
+int V4l2Obj::stream_on()
+{
+       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       int ret = 0;
+
+       ret = ioctl(m_fd, VIDIOC_STREAMON, &type);
+
+       if (ret) {
+               ERROR("VIDIOC_STREAMON failed: %s (%d)", strerror(errno), ret);
+       }
+
+       return ret;
+}
+
+/*
+* Disable streaming for V4L2 capture device
+*/
+int V4l2Obj::stream_off()
+{
+       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       int ret = -1;
+
+       if (m_fd <= 0) {
+               return ret;
+       }
+
+       ret = ioctl(m_fd, VIDIOC_STREAMOFF, &type);
+
+       if (ret) {
+               ERROR("VIDIOC_STREAMOFF failed: %s (%d)", strerror(errno), ret);
+       }
+
+       return ret;
+}
diff --git a/capture.h b/capture.h
new file mode 100755 (executable)
index 0000000..7e7a2f6
--- /dev/null
+++ b/capture.h
@@ -0,0 +1,54 @@
+#ifndef LOOP
+#define LOOPBACK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*fnptr_add_buf)(void *screen, uint32_t width, 
+               uint32_t height, uint32_t pixel_format, uint32_t *strides, 
+               uint32_t *offsets, uint32_t buf_fd, uint32_t *buf_id);
+
+typedef        int (*fnptr_crt_pln)(void *screen);
+
+typedef        int (*fnptr_set_pln_prop)(void *screen, uint8_t planeType,
+       uint32_t idx, uint8_t num_prop, const char **prop_name, uint32_t *prop_val);
+
+typedef int (*fnptr_queue_overlay_pln)(void *screen, uint32_t idx, uint32_t fb_id);
+typedef        int (*fnptr_disp_usr_pln)(void *screen);
+typedef        int (*fnptr_free_usr_pln)(void *screen, int block_time);
+
+struct control {
+    unsigned int main_cam;
+    unsigned int num_cams;
+    unsigned int num_jpeg;
+    unsigned int display_xres, display_yres;
+    bool pip;
+    bool jpeg;
+    bool exit;
+       void *screen;
+       void *screen1;
+       int drm_fd;
+    fnptr_add_buf add_overlay_buffer;
+       fnptr_crt_pln create_overlay_plane;
+       fnptr_set_pln_prop set_plane_property;
+       fnptr_queue_overlay_pln queue_overlay_plane;
+       fnptr_disp_usr_pln disp_user_plane;
+       fnptr_free_usr_pln free_overlay_plane;
+};
+
+extern struct control status;
+
+int init_loopback(void);
+void process_frame(void);
+void end_streaming(void);
+void exit_devices(void);
+void drm_disable_pip(void);
+void drm_enable_pip(void);
+void set_plane_properties(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LOOPBACK_H
diff --git a/clocks.qml b/clocks.qml
new file mode 100755 (executable)
index 0000000..d9694d1
--- /dev/null
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "content" as Content
+
+Rectangle {
+    id: root
+    width: 640; height: 320
+    color: "#646464"
+
+    ListView {
+        id: clockview
+        anchors.fill: parent
+        orientation: ListView.Horizontal
+        cacheBuffer: 2000
+        snapMode: ListView.SnapOneItem
+        highlightRangeMode: ListView.ApplyRange
+
+        delegate: Content.Clock { city: cityName; shift: timeShift }
+        model: ListModel {
+            ListElement { cityName: "New York"; timeShift: -4 }
+            ListElement { cityName: "London"; timeShift: 0 }
+            ListElement { cityName: "Oslo"; timeShift: 1 }
+            ListElement { cityName: "Mumbai"; timeShift: 5.5 }
+            ListElement { cityName: "Tokyo"; timeShift: 9 }
+            ListElement { cityName: "Brisbane"; timeShift: 10 }
+            ListElement { cityName: "Los Angeles"; timeShift: -8 }
+        }
+    }
+
+    Image {
+        anchors.left: parent.left
+        anchors.bottom: parent.bottom
+        anchors.margins: 10
+        source: "content/arrow.png"
+        rotation: -90
+        opacity: clockview.atXBeginning ? 0 : 0.5
+        Behavior on opacity { NumberAnimation { duration: 500 } }
+    }
+
+    Image {
+        anchors.right: parent.right
+        anchors.bottom: parent.bottom
+        anchors.margins: 10
+        source: "content/arrow.png"
+        rotation: 90
+        opacity: clockview.atXEnd ? 0 : 0.5
+        Behavior on opacity { NumberAnimation { duration: 500 } }
+    }
+}
diff --git a/cmem_buf.cpp b/cmem_buf.cpp
new file mode 100755 (executable)
index 0000000..5b65a53
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+/* This file defines function to allocate memory from CMEM pool */
+
+#include <iostream>
+#include <ti/cmem.h>
+#include <linux/dma-buf.h>
+#include <sys/ioctl.h>
+#include "cmem_buf.h"
+#include "error.h"
+
+#define CMEM_BLOCKID CMEM_CMABLOCKID
+
+CMEM_AllocParams cmem_alloc_params = {
+    CMEM_HEAP,      /* type */
+    CMEM_CACHED,    /* flags */
+    1               /* alignment */
+};
+
+bool g_is_cmem_init=false;
+bool g_is_cmem_exit=false;
+
+
+int BufObj::alloc_cmem_buffer(uint32_t size, uint32_t align, void **cmem_buf){
+    cmem_alloc_params.alignment = align;
+
+    *cmem_buf = CMEM_alloc2(CMEM_BLOCKID, size,
+        &cmem_alloc_params);
+
+    if(*cmem_buf == NULL){
+        ERROR("CMEM allocation failed");
+        return -1;
+    }
+
+    return CMEM_export_dmabuf(*cmem_buf);
+}
+
+void BufObj::free_cmem_buffer(void *cmem_buffer){
+    CMEM_free(cmem_buffer, &cmem_alloc_params);
+}
+
+ /* If the user space need to access the CMEM buffer for CPU based processing, it can set
+    the CMEM buffer cache settings using DMA_BUF IOCTLS. 
+    Cahche_operation setting for invalidation is (DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ))
+       Cache operation settting for buffer read write is (DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_READ
+       This piece of code is not used in the application and hence not tested
+*/
+int BufObj::dma_buf_do_cache_operation(int dma_buf_fd, uint32_t cache_operation){
+    int ret;
+    struct dma_buf_sync sync;
+    sync.flags = cache_operation;
+
+    ret = ioctl(dma_buf_fd, DMA_BUF_IOCTL_SYNC, &sync);
+
+    return ret;
+}
+
+BufObj::BufObj(uint32_t w, uint32_t h, uint32_t bpp,uint32_t fourcc, 
+               uint32_t align, uint32_t num_bufs){
+    m_width = w;
+    m_height = h;
+
+    /* Vivante HAL needs 16 pixel alignment in width and 4 pixel alignment in
+    * height and hence putting that restriction for now on all buffer allocation through CMEM.
+    */
+    m_stride = ((w + 15) & ~15) * bpp;
+    m_fourcc = fourcc;
+    m_num_bufs = num_bufs;
+
+    //Avoid calling CMEM init with every BufObj object
+    if(g_is_cmem_init == false){
+        CMEM_init();
+        g_is_cmem_init = true;
+    }
+
+    m_fd = (int *)malloc(num_bufs * sizeof(int));
+
+    if(m_fd == NULL){
+        ERROR("DispObj: m_fd array allocation failure\n");
+    }
+
+    m_fb_id = (uint32_t *)malloc(num_bufs * sizeof(int));
+    if(m_fb_id == NULL){
+        ERROR("DispObj: m_fb_id array allocation failure\n");
+    }
+
+    m_buf = (void **)malloc(num_bufs * sizeof(int));
+    if(m_buf == NULL){
+        ERROR("DispObj: m_buf array allocation failure\n");
+    }
+
+    for(uint32_t i = 0; i < num_bufs; i++){
+
+        /* Vivante HAL needs 16 pixel alignment in width and 4 pixel alignment in
+        * height and hence adjust the buffer size accrodingly.
+        */
+        uint32_t size = m_stride * ((m_height + 3) & ~3);
+
+        m_fd[i]  = alloc_cmem_buffer(size, align, &m_buf[i]);
+
+               if(m_buf[i] == NULL){
+                       ERROR("CMEM buffer allocation failed");
+               }
+
+        if(m_fd[i] < 0){
+            free_cmem_buffer(m_buf[i]);
+            ERROR("Cannot export CMEM buffer");
+        }
+    }
+}
+
+
+BufObj::~BufObj(){
+
+    uint32_t i;
+
+    for(i = 0; i < m_num_bufs; i++){
+        //Free the buffer
+        free_cmem_buffer(m_buf[i]);
+    }
+
+    free(m_fd);
+    free(m_fb_id);
+    free(m_buf);
+
+    if(g_is_cmem_exit == false){
+        CMEM_exit();
+        g_is_cmem_exit = true;
+    }
+}
diff --git a/cmem_buf.h b/cmem_buf.h
new file mode 100755 (executable)
index 0000000..7d73554
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef CMEM_BUF_H
+#define CMEM_BUF_H
+
+class BufObj {
+public:
+    BufObj(uint32_t w, uint32_t h, uint32_t bpp, uint32_t fourcc, uint32_t align, uint32_t num_bufs);
+    ~BufObj();
+
+    //If applications wants to do cache operations on buffer
+    int dma_buf_do_cache_operation(int dma_buf_fd, uint32_t cache_operation);
+
+    uint32_t m_fourcc;
+    uint32_t m_width;
+    uint32_t m_height; 
+    uint32_t m_stride;
+
+    int *m_fd;         
+    uint32_t *m_fb_id;
+    void **m_buf;
+
+private:
+    int alloc_cmem_buffer(unsigned int size, unsigned int align, void **cmem_buf);
+    void free_cmem_buffer(void *cmem_buffer);
+    uint32_t m_num_bufs;
+};
+
+#endif //CMEM_BUF_H
diff --git a/content/BuildButton.qml b/content/BuildButton.qml
new file mode 100755 (executable)
index 0000000..b44b158
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "logic.js" as Logic
+
+Item {
+    id: container
+    width: 64
+    height: 64
+    property alias source: img.source
+    property int index
+    property int row: 0
+    property int col: 0
+    property int towerType
+    property bool canBuild: true
+    property Item gameCanvas: parent.parent.parent
+    signal clicked()
+
+    Image {
+        id: img
+        opacity: (canBuild && gameCanvas.coins >= Logic.towerData[towerType-1].cost) ? 1.0 : 0.4
+    }
+    Text {
+        anchors.right: parent.right
+        font.pointSize: 14
+        font.bold: true
+        color: "#ffffff"
+        text: Logic.towerData[towerType - 1].cost
+    }
+    MouseArea {
+        anchors.fill: parent
+        onClicked: {
+            Logic.buildTower(towerType, col, row)
+            container.clicked()
+        }
+    }
+    Image {
+        visible: col == index && row != 0
+        source: "gfx/dialog-pointer.png"
+        anchors.top: parent.bottom
+        anchors.topMargin: 4
+        anchors.horizontalCenter: parent.horizontalCenter
+    }
+    Image {
+        visible: col == index && row == 0
+        source: "gfx/dialog-pointer.png"
+        rotation: 180
+        anchors.bottom: parent.top
+        anchors.bottomMargin: 6
+        anchors.horizontalCenter: parent.horizontalCenter
+    }
+}
diff --git a/content/Clock.qml b/content/Clock.qml
new file mode 100755 (executable)
index 0000000..9e6ed16
--- /dev/null
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+    id : clock
+    width: {
+        if (ListView.view && ListView.view.width >= 200)
+            return ListView.view.width / Math.floor(ListView.view.width / 200.0);
+        else
+            return 200;
+    }
+
+    height: {
+        if (ListView.view && ListView.view.height >= 240)
+            return ListView.view.height;
+        else
+            return 240;
+    }
+
+    property alias city: cityLabel.text
+    property int hours
+    property int minutes
+    property int seconds
+    property real shift
+    property bool night: false
+    property bool internationalTime: true //Unset for local time
+
+    function timeChanged() {
+        var date = new Date;
+        hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours()
+        night = ( hours < 7 || hours > 19 )
+        minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes()
+        seconds = date.getUTCSeconds();
+    }
+
+    Timer {
+        interval: 100; running: true; repeat: true;
+        onTriggered: clock.timeChanged()
+    }
+
+    Item {
+        anchors.centerIn: parent
+        width: 200; height: 240
+
+        Image { id: background; source: "clock.png"; visible: clock.night == false }
+        Image { source: "clock-night.png"; visible: clock.night == true }
+
+
+        Image {
+            x: 92.5; y: 27
+            source: "hour.png"
+            transform: Rotation {
+                id: hourRotation
+                origin.x: 7.5; origin.y: 73;
+                angle: (clock.hours * 30) + (clock.minutes * 0.5)
+                Behavior on angle {
+                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
+                }
+            }
+        }
+
+        Image {
+            x: 93.5; y: 17
+            source: "minute.png"
+            transform: Rotation {
+                id: minuteRotation
+                origin.x: 6.5; origin.y: 83;
+                angle: clock.minutes * 6
+                Behavior on angle {
+                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
+                }
+            }
+        }
+
+        Image {
+            x: 97.5; y: 20
+            source: "second.png"
+            transform: Rotation {
+                id: secondRotation
+                origin.x: 2.5; origin.y: 80;
+                angle: clock.seconds * 6
+                Behavior on angle {
+                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
+                }
+            }
+        }
+
+        Image {
+            anchors.centerIn: background; source: "center.png"
+        }
+
+        Text {
+            id: cityLabel
+            y: 210; anchors.horizontalCenter: parent.horizontalCenter
+            color: "white"
+            font.family: "Helvetica"
+            font.bold: true; font.pixelSize: 16
+            style: Text.Raised; styleColor: "black"
+        }
+    }
+}
diff --git a/content/GameCanvas.qml b/content/GameCanvas.qml
new file mode 100755 (executable)
index 0000000..e461a3a
--- /dev/null
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "logic.js" as Logic
+import "towers" as Towers
+
+Item {
+    id: grid
+
+    property int squareSize: 64
+    property int rows: 6
+    property int cols: 4
+    property Item canvas: grid
+    property int score: 0
+    property int coins: 100
+    property int lives: 3
+    property int waveNumber: 0
+    property int waveProgress: 0
+    property var towers
+    property var mobs
+    property bool gameRunning: false
+    property bool gameOver: false
+    property bool errored: false
+    property string errorString: ""
+
+    width: cols * squareSize
+    height: rows * squareSize
+
+    function freshState() {
+        lives = 3
+        coins = 100
+        score = 0
+        waveNumber = 0
+        waveProgress = 0
+        gameOver = false
+        gameRunning = false
+        towerMenu.shown = false
+        helpButton.comeBack();
+    }
+
+    Text {
+        id: errorText // Mostly for debug purposes
+        text: errorString
+        visible: errored
+        color: "red"
+        font.pixelSize: 18
+        wrapMode: Text.WordWrap
+        width: parent.width / 1.2
+        height: parent.height / 1.2
+        anchors.centerIn: parent
+        z: 1000
+    }
+
+    Timer {
+        interval: 16
+        running: true
+        repeat: true
+        onTriggered: Logic.tick()
+    }
+
+    MouseArea {
+        id: ma
+        anchors.fill: parent
+        onClicked: {
+            if (towerMenu.visible)
+                towerMenu.finish()
+            else
+                towerMenu.open(mouse.x, mouse.y)
+        }
+    }
+
+    Image {
+        id: towerMenu
+        visible: false
+        z: 1500
+        scale: 0.9
+        opacity: 0.7
+        property int dragDistance: 16
+        property int targetRow: 0
+        property int targetCol: 0
+        property bool shown: false
+        property bool towerExists: false
+
+        function finish() {
+            shown = false
+        }
+
+        function open(xp,yp) {
+            if (!grid.gameRunning)
+                return
+            targetRow = Logic.row(yp)
+            targetCol = Logic.col(xp)
+            if (targetRow == 0)
+                towerMenu.y = (targetRow + 1) * grid.squareSize
+            else
+                towerMenu.y = (targetRow - 1) * grid.squareSize
+            towerExists = (grid.towers[Logic.towerIdx(targetCol, targetRow)] != null)
+            shown = true
+            helpButton.goAway();
+        }
+
+        states: State {
+            name: "shown"; when: towerMenu.shown && !grid.gameOver
+            PropertyChanges { target: towerMenu; visible: true; scale: 1; opacity: 1 }
+        }
+
+        transitions: Transition {
+            PropertyAction { property: "visible" }
+            NumberAnimation { properties: "opacity,scale"; duration: 500; easing.type: Easing.OutElastic }
+        }
+
+        x: -32
+        source: "gfx/dialog.png"
+        Row {
+            id: buttonRow
+            height: 100
+            anchors.centerIn: parent
+            spacing: 8
+            BuildButton {
+                row: towerMenu.targetRow; col: towerMenu.targetCol
+                anchors.verticalCenter: parent.verticalCenter
+                towerType: 1; index: 0
+                canBuild: !towerMenu.towerExists
+                source: "gfx/dialog-melee.png"
+                onClicked: towerMenu.finish()
+            }
+            BuildButton {
+                row: towerMenu.targetRow; col: towerMenu.targetCol
+                anchors.verticalCenter: parent.verticalCenter
+                towerType: 2; index: 1
+                canBuild: !towerMenu.towerExists
+                source: "gfx/dialog-shooter.png"
+                onClicked: towerMenu.finish()
+            }
+            BuildButton {
+                row: towerMenu.targetRow; col: towerMenu.targetCol
+                anchors.verticalCenter: parent.verticalCenter
+                towerType: 3; index: 2
+                canBuild: !towerMenu.towerExists
+                source: "gfx/dialog-bomb.png"
+                onClicked: towerMenu.finish()
+            }
+            BuildButton {
+                row: towerMenu.targetRow; col: towerMenu.targetCol
+                anchors.verticalCenter: parent.verticalCenter
+                towerType: 4; index: 3
+                canBuild: !towerMenu.towerExists
+                source: "gfx/dialog-factory.png"
+                onClicked: towerMenu.finish()
+            }
+        }
+    }
+
+
+    Keys.onPressed: { // Cheat Codes while Testing
+        if (event.key == Qt.Key_Up && (event.modifiers & Qt.ShiftModifier))
+            grid.coins += 10;
+        if (event.key == Qt.Key_Left && (event.modifiers & Qt.ShiftModifier))
+            grid.lives += 1;
+        if (event.key == Qt.Key_Down && (event.modifiers & Qt.ShiftModifier))
+            Logic.gameState.waveProgress += 1000;
+        if (event.key == Qt.Key_Right && (event.modifiers & Qt.ShiftModifier))
+            Logic.endGame();
+    }
+
+    Image {
+        id: helpButton
+        z: 1010
+        source: "gfx/button-help.png"
+        function goAway() {
+            helpMA.enabled = false;
+            helpButton.opacity = 0;
+        }
+        function comeBack() {
+            helpMA.enabled = true;
+            helpButton.opacity = 1;
+        }
+        Behavior on opacity { NumberAnimation {} }
+        MouseArea {
+            id: helpMA
+            anchors.fill: parent
+            onClicked: {helpImage.visible = true; helpButton.visible = false;}
+        }
+
+        anchors.horizontalCenter: parent.horizontalCenter
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 0
+    }
+
+    Image {
+        id: helpImage
+        z: 1010
+        source: "gfx/help.png"
+        anchors.fill: parent
+        visible: false
+        MouseArea {
+            anchors.fill: parent
+            onClicked: helpImage.visible = false;
+        }
+    }
+
+}
diff --git a/content/GameOverScreen.qml b/content/GameOverScreen.qml
new file mode 100755 (executable)
index 0000000..db045ba
--- /dev/null
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Particles 2.0
+import "logic.js" as Logic
+
+Item {
+    id: gameOverScreen
+    width: 320
+    height: 400
+    property GameCanvas gameCanvas
+
+    Image {
+        id: img
+        source: "gfx/text-gameover.png"
+        anchors.centerIn: parent
+    }
+
+    ParticleSystem {
+        anchors.fill: parent
+        ImageParticle {
+            id: cloud
+            source: "gfx/cloud.png"
+            alphaVariation: 0.25
+            opacity: 0.25
+        }
+
+        Wander {
+            xVariance: 100;
+            pace: 1;
+        }
+
+        Emitter {
+            id: cloudLeft
+            width: 160
+            height: 160
+            anchors.right: parent.left
+            emitRate: 0.5
+            lifeSpan: 12000
+            velocity: PointDirection{ x: 64; xVariation: 2; yVariation: 2 }
+            size: 160
+        }
+
+        Emitter {
+            id: cloudRight
+            width: 160
+            height: 160
+            anchors.left: parent.right
+            emitRate: 0.5
+            lifeSpan: 12000
+            velocity: PointDirection{ x: -64; xVariation: 2; yVariation: 2 }
+            size: 160
+        }
+    }
+
+
+    Text {
+        visible: gameCanvas != undefined
+        text: "You saved " + gameCanvas.score + " fishes!"
+        anchors.top: img.bottom
+        anchors.topMargin: 12
+        anchors.horizontalCenter: parent.horizontalCenter
+        font.bold: true
+        color: "#000000"
+        opacity: 0.5
+    }
+
+    Image {
+        source: "gfx/button-play.png"
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 0
+        MouseArea {
+            anchors.fill: parent
+            onClicked: gameCanvas.gameOver = false//This will actually trigger the state change in main.qml
+        }
+    }
+}
diff --git a/content/InfoBar.qml b/content/InfoBar.qml
new file mode 100755 (executable)
index 0000000..ff5738d
--- /dev/null
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+    height: childrenRect.height
+
+    // Display the number of lives
+    Row {
+        anchors.left: parent.left
+        anchors.leftMargin: 10
+        spacing: 5
+        Repeater {
+            id: rep
+            model: Math.min(10, canvas.lives)
+            delegate: Image { source: "gfx/lifes.png" }
+        }
+    }
+
+    // Display the number of fishes saved
+    Row {
+        anchors.right: points.left
+        anchors.rightMargin: 20
+        spacing: 5
+        Image { source: "gfx/scores.png" }
+        Text {
+            text: canvas.score
+            font.bold: true
+        }
+    }
+
+    // Display the number of coins
+    Row {
+        id: points
+        anchors.right: parent.right
+        anchors.rightMargin: 10
+        spacing: 5
+        Image { source: "gfx/points.png" }
+        Text {
+            id: pointsLabel
+            text: canvas.coins
+            font.bold: true
+        }
+    }
+}
+
diff --git a/content/NewGameScreen.qml b/content/NewGameScreen.qml
new file mode 100755 (executable)
index 0000000..f078300
--- /dev/null
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+// This is the first screen.
+// It shows the logo and emit a startButtonClicked signal
+// when the user press the "PLAY" button.
+
+Item {
+    id: newGameScreen
+    width: 320
+    height: 480
+
+    signal startButtonClicked
+
+    Image {
+        source: "gfx/logo.png"
+        anchors.top: parent.top
+        anchors.topMargin: 60
+    }
+
+    Image {
+        source: "gfx/logo-fish.png"
+        anchors.top: parent.top
+
+        SequentialAnimation on x {
+            loops: Animation.Infinite
+            NumberAnimation { from: x + 148; to: x + 25; duration: 2000; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: x + 25; to: x + 148; duration: 1600; easing.type: Easing.InOutQuad }
+        }
+        SequentialAnimation on anchors.topMargin {
+            loops: Animation.Infinite
+            NumberAnimation { from: 100; to: 60; duration: 1600; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: 60; to: 100; duration: 2000; easing.type: Easing.InOutQuad }
+        }
+    }
+
+    Image {
+        source: "gfx/logo-bubble.png"
+        anchors.top: parent.top
+
+        SequentialAnimation on x {
+            loops: Animation.Infinite
+            NumberAnimation { from: x + 140; to: x + 40; duration: 2000; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: x + 40; to: x + 140; duration: 1600; easing.type: Easing.InOutQuad }
+        }
+        SequentialAnimation on anchors.topMargin {
+            loops: Animation.Infinite
+            NumberAnimation { from: 100; to: 60; duration: 1600; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: 60; to: 100; duration: 2000; easing.type: Easing.InOutQuad }
+        }
+        SequentialAnimation on width {
+            loops: Animation.Infinite
+            NumberAnimation { from: 140; to: 160; duration: 1000; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: 160; to: 140; duration: 800; easing.type: Easing.InOutQuad }
+        }
+        SequentialAnimation on height {
+            loops: Animation.Infinite
+            NumberAnimation { from: 150; to: 140; duration: 800; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: 140; to: 150; duration: 1000; easing.type: Easing.InOutQuad }
+        }
+    }
+
+    Image {
+        source: "gfx/button-play.png"
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 60
+        MouseArea {
+            anchors.fill: parent
+            onClicked: newGameScreen.startButtonClicked()
+        }
+    }
+}
diff --git a/content/SoundEffect.qml b/content/SoundEffect.qml
new file mode 100755 (executable)
index 0000000..136b33a
--- /dev/null
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+//Proxies a SoundEffect if QtMultimedia is installed
+Item {
+    id: container
+    property QtObject effect: Qt.createQmlObject("import QtMultimedia 5.0; SoundEffect{ source: '" + container.source + "'; muted: !Qt.application.active }", container);
+    property url source: ""
+    onSourceChanged: if (effect != null) effect.source = source;
+    function play() {
+        if (effect != null)
+            effect.play();
+    }
+}
diff --git a/content/arrow.png b/content/arrow.png
new file mode 100755 (executable)
index 0000000..e437312
Binary files /dev/null and b/content/arrow.png differ
diff --git a/content/audio/bomb-action.wav b/content/audio/bomb-action.wav
new file mode 100755 (executable)
index 0000000..b334dc1
Binary files /dev/null and b/content/audio/bomb-action.wav differ
diff --git a/content/audio/catch-action.wav b/content/audio/catch-action.wav
new file mode 100755 (executable)
index 0000000..3e22124
Binary files /dev/null and b/content/audio/catch-action.wav differ
diff --git a/content/audio/catch.wav b/content/audio/catch.wav
new file mode 100755 (executable)
index 0000000..d3eade8
Binary files /dev/null and b/content/audio/catch.wav differ
diff --git a/content/audio/currency.wav b/content/audio/currency.wav
new file mode 100755 (executable)
index 0000000..0d9ef2c
Binary files /dev/null and b/content/audio/currency.wav differ
diff --git a/content/audio/factory-action.wav b/content/audio/factory-action.wav
new file mode 100755 (executable)
index 0000000..a2ace6c
Binary files /dev/null and b/content/audio/factory-action.wav differ
diff --git a/content/audio/melee-action.wav b/content/audio/melee-action.wav
new file mode 100755 (executable)
index 0000000..d325af4
Binary files /dev/null and b/content/audio/melee-action.wav differ
diff --git a/content/audio/projectile-action.wav b/content/audio/projectile-action.wav
new file mode 100755 (executable)
index 0000000..4e2284f
Binary files /dev/null and b/content/audio/projectile-action.wav differ
diff --git a/content/audio/shooter-action.wav b/content/audio/shooter-action.wav
new file mode 100755 (executable)
index 0000000..3e12b94
Binary files /dev/null and b/content/audio/shooter-action.wav differ
diff --git a/content/background.png b/content/background.png
new file mode 100755 (executable)
index 0000000..a885950
Binary files /dev/null and b/content/background.png differ
diff --git a/content/center.png b/content/center.png
new file mode 100755 (executable)
index 0000000..7fbd802
Binary files /dev/null and b/content/center.png differ
diff --git a/content/clock-night.png b/content/clock-night.png
new file mode 100755 (executable)
index 0000000..cc7151a
Binary files /dev/null and b/content/clock-night.png differ
diff --git a/content/clock.png b/content/clock.png
new file mode 100644 (file)
index 0000000..462edac
Binary files /dev/null and b/content/clock.png differ
diff --git a/content/gfx/background.png b/content/gfx/background.png
new file mode 100755 (executable)
index 0000000..d548b93
Binary files /dev/null and b/content/gfx/background.png differ
diff --git a/content/gfx/bomb-action.png b/content/gfx/bomb-action.png
new file mode 100755 (executable)
index 0000000..42da5d7
Binary files /dev/null and b/content/gfx/bomb-action.png differ
diff --git a/content/gfx/bomb-idle.png b/content/gfx/bomb-idle.png
new file mode 100755 (executable)
index 0000000..3bd62e2
Binary files /dev/null and b/content/gfx/bomb-idle.png differ
diff --git a/content/gfx/bomb.png b/content/gfx/bomb.png
new file mode 100755 (executable)
index 0000000..380da7d
Binary files /dev/null and b/content/gfx/bomb.png differ
diff --git a/content/gfx/button-help.png b/content/gfx/button-help.png
new file mode 100755 (executable)
index 0000000..aecebc1
Binary files /dev/null and b/content/gfx/button-help.png differ
diff --git a/content/gfx/button-play.png b/content/gfx/button-play.png
new file mode 100755 (executable)
index 0000000..6cdad6c
Binary files /dev/null and b/content/gfx/button-play.png differ
diff --git a/content/gfx/catch-action.png b/content/gfx/catch-action.png
new file mode 100755 (executable)
index 0000000..78ca9fe
Binary files /dev/null and b/content/gfx/catch-action.png differ
diff --git a/content/gfx/catch.png b/content/gfx/catch.png
new file mode 100755 (executable)
index 0000000..b7620fe
Binary files /dev/null and b/content/gfx/catch.png differ
diff --git a/content/gfx/cloud.png b/content/gfx/cloud.png
new file mode 100755 (executable)
index 0000000..d7c35f8
Binary files /dev/null and b/content/gfx/cloud.png differ
diff --git a/content/gfx/currency.png b/content/gfx/currency.png
new file mode 100755 (executable)
index 0000000..1571341
Binary files /dev/null and b/content/gfx/currency.png differ
diff --git a/content/gfx/dialog-bomb.png b/content/gfx/dialog-bomb.png
new file mode 100755 (executable)
index 0000000..708d916
Binary files /dev/null and b/content/gfx/dialog-bomb.png differ
diff --git a/content/gfx/dialog-factory.png b/content/gfx/dialog-factory.png
new file mode 100755 (executable)
index 0000000..d2e2a48
Binary files /dev/null and b/content/gfx/dialog-factory.png differ
diff --git a/content/gfx/dialog-melee.png b/content/gfx/dialog-melee.png
new file mode 100755 (executable)
index 0000000..069d18d
Binary files /dev/null and b/content/gfx/dialog-melee.png differ
diff --git a/content/gfx/dialog-pointer.png b/content/gfx/dialog-pointer.png
new file mode 100755 (executable)
index 0000000..9b51a09
Binary files /dev/null and b/content/gfx/dialog-pointer.png differ
diff --git a/content/gfx/dialog-shooter.png b/content/gfx/dialog-shooter.png
new file mode 100755 (executable)
index 0000000..af980ca
Binary files /dev/null and b/content/gfx/dialog-shooter.png differ
diff --git a/content/gfx/dialog.png b/content/gfx/dialog.png
new file mode 100755 (executable)
index 0000000..d528ba7
Binary files /dev/null and b/content/gfx/dialog.png differ
diff --git a/content/gfx/factory-action.png b/content/gfx/factory-action.png
new file mode 100755 (executable)
index 0000000..8981678
Binary files /dev/null and b/content/gfx/factory-action.png differ
diff --git a/content/gfx/factory-idle.png b/content/gfx/factory-idle.png
new file mode 100755 (executable)
index 0000000..a145582
Binary files /dev/null and b/content/gfx/factory-idle.png differ
diff --git a/content/gfx/factory.png b/content/gfx/factory.png
new file mode 100755 (executable)
index 0000000..bfb9f3f
Binary files /dev/null and b/content/gfx/factory.png differ
diff --git a/content/gfx/grid.png b/content/gfx/grid.png
new file mode 100755 (executable)
index 0000000..b595552
Binary files /dev/null and b/content/gfx/grid.png differ
diff --git a/content/gfx/help.png b/content/gfx/help.png
new file mode 100755 (executable)
index 0000000..4654e4c
Binary files /dev/null and b/content/gfx/help.png differ
diff --git a/content/gfx/lifes.png b/content/gfx/lifes.png
new file mode 100755 (executable)
index 0000000..135310b
Binary files /dev/null and b/content/gfx/lifes.png differ
diff --git a/content/gfx/logo-bubble.png b/content/gfx/logo-bubble.png
new file mode 100755 (executable)
index 0000000..136151c
Binary files /dev/null and b/content/gfx/logo-bubble.png differ
diff --git a/content/gfx/logo-fish.png b/content/gfx/logo-fish.png
new file mode 100755 (executable)
index 0000000..c41833a
Binary files /dev/null and b/content/gfx/logo-fish.png differ
diff --git a/content/gfx/logo.png b/content/gfx/logo.png
new file mode 100755 (executable)
index 0000000..787ac99
Binary files /dev/null and b/content/gfx/logo.png differ
diff --git a/content/gfx/melee-action.png b/content/gfx/melee-action.png
new file mode 100755 (executable)
index 0000000..c53873b
Binary files /dev/null and b/content/gfx/melee-action.png differ
diff --git a/content/gfx/melee-idle.png b/content/gfx/melee-idle.png
new file mode 100755 (executable)
index 0000000..621d9df
Binary files /dev/null and b/content/gfx/melee-idle.png differ
diff --git a/content/gfx/melee.png b/content/gfx/melee.png
new file mode 100755 (executable)
index 0000000..ab24015
Binary files /dev/null and b/content/gfx/melee.png differ
diff --git a/content/gfx/mob-idle.png b/content/gfx/mob-idle.png
new file mode 100755 (executable)
index 0000000..dedacc7
Binary files /dev/null and b/content/gfx/mob-idle.png differ
diff --git a/content/gfx/mob.png b/content/gfx/mob.png
new file mode 100755 (executable)
index 0000000..7569c35
Binary files /dev/null and b/content/gfx/mob.png differ
diff --git a/content/gfx/points.png b/content/gfx/points.png
new file mode 100755 (executable)
index 0000000..1d2386d
Binary files /dev/null and b/content/gfx/points.png differ
diff --git a/content/gfx/projectile-action.png b/content/gfx/projectile-action.png
new file mode 100755 (executable)
index 0000000..aa2e650
Binary files /dev/null and b/content/gfx/projectile-action.png differ
diff --git a/content/gfx/projectile.png b/content/gfx/projectile.png
new file mode 100755 (executable)
index 0000000..c25a0c3
Binary files /dev/null and b/content/gfx/projectile.png differ
diff --git a/content/gfx/scores.png b/content/gfx/scores.png
new file mode 100755 (executable)
index 0000000..af757fe
Binary files /dev/null and b/content/gfx/scores.png differ
diff --git a/content/gfx/shooter-action.png b/content/gfx/shooter-action.png
new file mode 100755 (executable)
index 0000000..08e7e30
Binary files /dev/null and b/content/gfx/shooter-action.png differ
diff --git a/content/gfx/shooter-idle.png b/content/gfx/shooter-idle.png
new file mode 100755 (executable)
index 0000000..663098d
Binary files /dev/null and b/content/gfx/shooter-idle.png differ
diff --git a/content/gfx/shooter.png b/content/gfx/shooter.png
new file mode 100755 (executable)
index 0000000..d44401e
Binary files /dev/null and b/content/gfx/shooter.png differ
diff --git a/content/gfx/sunlight.png b/content/gfx/sunlight.png
new file mode 100755 (executable)
index 0000000..d1c7042
Binary files /dev/null and b/content/gfx/sunlight.png differ
diff --git a/content/gfx/text-1.png b/content/gfx/text-1.png
new file mode 100755 (executable)
index 0000000..3ea399c
Binary files /dev/null and b/content/gfx/text-1.png differ
diff --git a/content/gfx/text-2.png b/content/gfx/text-2.png
new file mode 100755 (executable)
index 0000000..934a481
Binary files /dev/null and b/content/gfx/text-2.png differ
diff --git a/content/gfx/text-3.png b/content/gfx/text-3.png
new file mode 100755 (executable)
index 0000000..47523f5
Binary files /dev/null and b/content/gfx/text-3.png differ
diff --git a/content/gfx/text-blank.png b/content/gfx/text-blank.png
new file mode 100755 (executable)
index 0000000..4a687b2
Binary files /dev/null and b/content/gfx/text-blank.png differ
diff --git a/content/gfx/text-gameover.png b/content/gfx/text-gameover.png
new file mode 100755 (executable)
index 0000000..4f53ef0
Binary files /dev/null and b/content/gfx/text-gameover.png differ
diff --git a/content/gfx/text-go.png b/content/gfx/text-go.png
new file mode 100755 (executable)
index 0000000..bfc26f7
Binary files /dev/null and b/content/gfx/text-go.png differ
diff --git a/content/gfx/wave.png b/content/gfx/wave.png
new file mode 100755 (executable)
index 0000000..f97426c
Binary files /dev/null and b/content/gfx/wave.png differ
diff --git a/content/hour.png b/content/hour.png
new file mode 100755 (executable)
index 0000000..9f33fc5
Binary files /dev/null and b/content/hour.png differ
diff --git a/content/logic.js b/content/logic.js
new file mode 100755 (executable)
index 0000000..7e087d8
--- /dev/null
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+.pragma library // Shared game state
+.import QtQuick 2.0 as QQ
+
+// Game Stuff
+var gameState // Local reference
+function getGameState() { return gameState; }
+
+var towerData = [ // Name and cost, stats are in the delegate per instance
+    { "name": "Melee", "cost": 20 },
+    { "name": "Ranged", "cost": 50 },
+    { "name": "Bomb", "cost": 75 },
+    { "name": "Factory", "cost": 25 }
+]
+
+var waveBaseData = [300, 290, 280, 270, 220, 180, 160, 80, 80, 80, 30, 30, 30, 30];
+var waveData = [];
+
+var towerComponents = new Array(towerData.length);
+var mobComponent = Qt.createComponent("mobs/MobBase.qml");
+
+function endGame()
+{
+    gameState.gameRunning = false;
+    gameState.gameOver = true;
+    for (var i = 0; i < gameState.cols; i++) {
+        for (var j = 0; j < gameState.rows; j++) {
+            if (gameState.towers[towerIdx(i, j)]) {
+                gameState.towers[towerIdx(i, j)].destroy();
+                gameState.towers[towerIdx(i, j)] = null;
+            }
+        }
+        for (var j in gameState.mobs[i])
+            gameState.mobs[i][j].destroy();
+        gameState.mobs[i].splice(0,gameState.mobs[i].length); //Leaves queue reusable
+    }
+}
+
+function startGame(gameCanvas)
+{
+    waveData = new Array();
+    for (var i in waveBaseData)
+        waveData[i] = waveBaseData[i];
+    gameState.freshState();
+    for (var i = 0; i < gameCanvas.cols; i++) {
+        for (var j = 0; j < gameCanvas.rows; j++)
+            gameState.towers[towerIdx(i, j)] = null;
+        gameState.mobs[i] = new Array();
+    }
+    gameState.towers[towerIdx(0, 0)] = newTower(3, 0, 0);//Start with a starfish in the corner
+    gameState.gameRunning = true;
+    gameState.gameOver = false;
+}
+
+function newGameState(gameCanvas)
+{
+    for (var i = 0; i < towerComponents.length; i++) {
+        towerComponents[i] = Qt.createComponent("towers/" + towerData[i].name + ".qml");
+        if (towerComponents[i].status == QQ.Component.Error) {
+            gameCanvas.errored = true;
+            gameCanvas.errorString += "Loading Tower " + towerData[i].name + "\n" + (towerComponents[i].errorString());
+            console.log(towerComponents[i].errorString());
+        }
+    }
+    gameState = gameCanvas;
+    gameState.freshState();
+    gameState.towers = new Array(gameCanvas.rows * gameCanvas.cols);
+    gameState.mobs = new Array(gameCanvas.cols);
+    return gameState;
+}
+
+function row(y)
+{
+    return Math.floor(y / gameState.squareSize);
+}
+
+function col(x)
+{
+    return Math.floor(x / gameState.squareSize);
+}
+
+function towerIdx(x, y)
+{
+    return y + (x * gameState.rows);
+}
+
+function newMob(col)
+{
+    var ret = mobComponent.createObject(gameState.canvas,
+        { "col" : col,
+          "speed" : (Math.min(2.0, 0.10 * (gameState.waveNumber + 1))),
+          "y" : gameState.canvas.height });
+    gameState.mobs[col].push(ret);
+    return ret;
+}
+
+function newTower(type, row, col)
+{
+    var ret = towerComponents[type].createObject(gameState.canvas);
+    ret.row = row;
+    ret.col = col;
+    ret.fireCounter = ret.rof;
+    ret.spawn();
+    return ret;
+}
+
+function buildTower(type, x, y)
+{
+    if (gameState.towers[towerIdx(x,y)] != null) {
+        if (type <= 0) {
+            gameState.towers[towerIdx(x,y)].sell();
+            gameState.towers[towerIdx(x,y)] = null;
+        }
+    } else {
+        if (gameState.coins < towerData[type - 1].cost)
+            return;
+        gameState.towers[towerIdx(x, y)] = newTower(type - 1, y, x);
+        gameState.coins -= towerData[type - 1].cost;
+    }
+}
+
+function killMob(col, mob)
+{
+    if (!mob)
+        return;
+    var idx = gameState.mobs[col].indexOf(mob);
+    if (idx == -1 || !mob.hp)
+        return;
+    mob.hp = 0;
+    mob.die();
+    gameState.mobs[col].splice(idx,1);
+}
+
+function killTower(row, col)
+{
+    var tower = gameState.towers[towerIdx(col, row)];
+    if (!tower)
+        return;
+    tower.hp = 0;
+    tower.die();
+    gameState.towers[towerIdx(col, row)] = null;
+}
+
+function tick()
+{
+    if (!gameState.gameRunning)
+        return;
+
+    // Spawn
+    gameState.waveProgress += 1;
+    var i = gameState.waveProgress;
+    var j = 0;
+    while (i > 0 && j < waveData.length)
+        i -= waveData[j++];
+    if ( i == 0 ) // Spawn a mob
+        newMob(Math.floor(Math.random() * gameState.cols));
+    if ( j == waveData.length ) { // Next Wave
+        gameState.waveNumber += 1;
+        gameState.waveProgress = 0;
+        var waveModifier = 10; // Constant governing how much faster the next wave is to spawn (not fish speed)
+        for (var k in waveData ) // Slightly faster
+            if (waveData[k] > waveModifier)
+                waveData[k] -= waveModifier;
+    }
+
+    // Towers Attack
+    for (var j in gameState.towers) {
+        var tower = gameState.towers[j];
+        if (tower == null)
+            continue;
+        if (tower.fireCounter > 0) {
+            tower.fireCounter -= 1;
+            continue;
+        }
+        var column = tower.col;
+        for (var k in gameState.mobs[column]) {
+            var conflict = gameState.mobs[column][k];
+            if (conflict.y <= gameState.canvas.height && conflict.y + conflict.height > tower.y
+                && conflict.y - ((tower.row + 1) * gameState.squareSize) < gameState.squareSize * tower.range) { // In Range
+                tower.fire();
+                tower.fireCounter = tower.rof;
+                conflict.hit(tower.damage);
+            }
+        }
+
+        // Income
+        if (tower.income) {
+            gameState.coins += tower.income;
+            tower.fire();
+            tower.fireCounter = tower.rof;
+        }
+    }
+
+    // Mobs move
+    for (var i = 0; i < gameState.cols; i++) {
+        for (var j = 0; j < gameState.mobs[i].length; j++) {
+            var mob = gameState.mobs[i][j];
+            var newPos = gameState.mobs[i][j].y - gameState.mobs[i][j].speed;
+            if (newPos < 0) {
+                gameState.lives -= 1;
+                killMob(i, mob);
+                if (gameState.lives <= 0)
+                    endGame();
+                continue;
+            }
+            var conflict = gameState.towers[towerIdx(i, row(newPos))];
+            if (conflict != null) {
+                if (mob.y < conflict.y + gameState.squareSize)
+                    gameState.mobs[i][j].y += gameState.mobs[i][j].speed * 10; // Moved inside tower, now hurry back out
+                if (mob.fireCounter > 0) {
+                    mob.fireCounter--;
+                } else {
+                    gameState.mobs[i][j].fire();
+                    conflict.hp -= mob.damage;
+                    if (conflict.hp <= 0)
+                        killTower(conflict.row, conflict.col);
+                    mob.fireCounter = mob.rof;
+                }
+            } else {
+                gameState.mobs[i][j].y = newPos;
+            }
+        }
+    }
+
+}
diff --git a/content/minute.png b/content/minute.png
new file mode 100755 (executable)
index 0000000..e2f216c
Binary files /dev/null and b/content/minute.png differ
diff --git a/content/mobs/MobBase.qml b/content/mobs/MobBase.qml
new file mode 100755 (executable)
index 0000000..b281408
--- /dev/null
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "../logic.js" as Logic
+import ".."
+
+Item  {
+    id: container
+    property string name: "Fish"
+    property int col: 0
+    property real hp: 3
+    property real damage: 1
+    property real speed: 0.25
+    property int rof: 30 //In ticks
+    property int fireCounter: 0
+    property bool dying: false
+    width: parent ? parent.squareSize : 0
+    height: parent ? parent.squareSize : 0
+    x: col * width
+    z: 1001
+    function fire() { }
+
+    function die() {
+        if (dying)
+            return;
+        dying = true;
+        bubble.jumpTo("burst");
+        if (fishSprite.currentSprite == "front")
+            fishSprite.jumpTo(Math.random() > 0.5 ? "left" : "right" );
+        fishSwim.start();
+        Logic.gameState.score += 1;
+        killedSound.play();
+        bubble.scale = 0.9
+        destroy(350);
+    }
+
+    function inked() {
+        if (hp > 0)
+            ink.jumpTo("dirty");
+    }
+
+    function hit(dmg) {
+        hp -= dmg;
+
+        if (hp <= 0)
+            Logic.killMob(col, container);
+    }
+
+    Component.onCompleted: spawnSound.play()
+
+    SoundEffect {
+        id: spawnSound
+        source: "../audio/catch.wav"
+    }
+    SoundEffect {
+        id: killedSound
+        source: "../audio/catch-action.wav"
+    }
+
+    SpriteSequence {
+        id: fishSprite
+        width: 64
+        height: 64
+        interpolate: false
+        goalSprite: ""
+
+        Sprite {
+            name: "left"
+            source: "../gfx/mob-idle.png"
+            frameWidth: 64
+            frameHeight: 64
+            frameCount: 1
+            frameDuration: 800
+            frameDurationVariation: 400
+            to: { "front" : 1 }
+        }
+
+        Sprite {
+            name: "front"
+            source: "../gfx/mob-idle.png"
+            frameCount: 1
+            frameX: 64
+            frameWidth: 64
+            frameHeight: 64
+            frameDuration: 800
+            frameDurationVariation: 400
+            to: { "left" : 1, "right" : 1 }
+        }
+
+        Sprite {
+            name: "right"
+            source: "../gfx/mob-idle.png"
+            frameCount: 1
+            frameX: 128
+            frameWidth: 64
+            frameHeight: 64
+            frameDuration: 800
+            frameDurationVariation: 400
+            to: { "front" : 1 }
+        }
+
+
+        Sprite { //WORKAROUND: This prevents the triggering of a rendering error which is currently under investigation.
+            name: "dummy"
+            source: "../gfx/melee-idle.png"
+            frameCount: 8
+            frameWidth: 64
+            frameHeight: 64
+            frameX: 0
+            frameDuration: 200
+        }
+
+        NumberAnimation on x {
+            id: fishSwim
+            running: false
+            property bool goingLeft: fishSprite.currentSprite == "right"
+            to: goingLeft ? -360 : 360
+            duration: 300
+        }
+    }
+
+    SpriteSequence {
+        id: bubble
+        width: 64
+        height: 64
+        scale: 0.4 + (0.2  * hp)
+        interpolate: false
+        goalSprite: ""
+
+        Behavior on scale {
+            NumberAnimation { duration: 150; easing.type: Easing.OutBack }
+        }
+
+        Sprite {
+            name: "big"
+            source: "../gfx/catch.png"
+            frameCount: 1
+            to: { "burst" : 0 }
+        }
+
+        Sprite {
+            name: "burst"
+            source: "../gfx/catch-action.png"
+            frameCount: 3
+            frameX: 64
+            frameDuration: 200
+        }
+
+        Sprite { //WORKAROUND: This prevents the triggering of a rendering error which is currently under investigation.
+            name: "dummy"
+            source: "../gfx/melee-idle.png"
+            frameCount: 8
+            frameWidth: 64
+            frameHeight: 64
+            frameX: 0
+            frameDuration: 200
+        }
+        SequentialAnimation on width {
+            loops: Animation.Infinite
+            NumberAnimation { from: width * 1; to: width * 1.1; duration: 800; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: width * 1.1; to: width * 1; duration: 1000; easing.type: Easing.InOutQuad }
+        }
+        SequentialAnimation on height {
+            loops: Animation.Infinite
+            NumberAnimation { from: height * 1; to: height * 1.15; duration: 1200; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: height * 1.15; to: height * 1; duration: 1000; easing.type: Easing.InOutQuad }
+        }
+    }
+
+    SpriteSequence {
+        id: ink
+        width: 64
+        height: 64
+        scale: bubble.scale
+        goalSprite: ""
+
+        Sprite {
+            name: "clean"
+            source: "../gfx/projectile-action.png"
+            frameCount: 1
+            frameX: 0
+            frameWidth: 64
+            frameHeight: 64
+        }
+        Sprite {
+            name: "dirty"
+            source: "../gfx/projectile-action.png"
+            frameCount: 3
+            frameX: 64
+            frameWidth: 64
+            frameHeight: 64
+            frameDuration: 150
+            to: {"clean":1}
+        }
+
+        Sprite { //WORKAROUND: This prevents the triggering of a rendering error which is currently under investigation.
+            name: "dummy"
+            source: "../gfx/melee-idle.png"
+            frameCount: 8
+            frameWidth: 64
+            frameHeight: 64
+            frameX: 0
+            frameDuration: 200
+        }
+        SequentialAnimation on width {
+            loops: Animation.Infinite
+            NumberAnimation { from: width * 1; to: width * 1.1; duration: 800; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: width * 1.1; to: width * 1; duration: 1000; easing.type: Easing.InOutQuad }
+        }
+        SequentialAnimation on height {
+            loops: Animation.Infinite
+            NumberAnimation { from: height * 1; to: height * 1.15; duration: 1200; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: height * 1.15; to: height * 1; duration: 1000; easing.type: Easing.InOutQuad }
+        }
+
+    }
+
+    SequentialAnimation on x {
+        loops: Animation.Infinite
+        NumberAnimation { from: x; to: x - 5; duration: 900; easing.type: Easing.InOutQuad }
+        NumberAnimation { from: x - 5; to: x; duration: 900; easing.type: Easing.InOutQuad }
+    }
+}
+
diff --git a/content/quit.png b/content/quit.png
new file mode 100755 (executable)
index 0000000..b822057
Binary files /dev/null and b/content/quit.png differ
diff --git a/content/second.png b/content/second.png
new file mode 100755 (executable)
index 0000000..d95d99e
Binary files /dev/null and b/content/second.png differ
diff --git a/content/towers/Bomb.qml b/content/towers/Bomb.qml
new file mode 100755 (executable)
index 0000000..85e0c8e
--- /dev/null
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "../logic.js" as Logic
+import ".."
+
+TowerBase {
+    id: container
+    hp: 10
+    range: 0.4
+    rof: 10
+    property real detonationRange: 2.5
+
+    function fire() {
+        sound.play()
+        sprite.jumpTo("shoot")
+        animDelay.start()
+    }
+
+    function finishFire() {
+        var sCol = Math.max(0, col - 1)
+        var eCol = Math.min(Logic.gameState.cols - 1, col + 1)
+        var killList = new Array()
+        for (var i = sCol; i <= eCol; i++) {
+            for (var j = 0; j < Logic.gameState.mobs[i].length; j++)
+                if (Math.abs(Logic.gameState.mobs[i][j].y - container.y) < Logic.gameState.squareSize * detonationRange)
+                    killList.push(Logic.gameState.mobs[i][j])
+            while (killList.length > 0)
+                Logic.killMob(i, killList.pop())
+        }
+        Logic.killTower(row, col);
+    }
+
+    Timer {
+        id: animDelay
+        running: false
+        interval: shootState.frameCount * shootState.frameDuration
+        onTriggered: finishFire()
+    }
+
+    function die()
+    {
+        destroy() // No blink, because we usually meant to die
+    }
+
+    SoundEffect {
+        id: sound
+        source: "../audio/bomb-action.wav"
+    }
+
+    SpriteSequence {
+        id: sprite
+        width: 64
+        height: 64
+        interpolate: false
+        goalSprite: ""
+
+        Sprite {
+            name: "idle"
+            source: "../gfx/bomb-idle.png"
+            frameCount: 4
+            frameDuration: 800
+        }
+
+        Sprite {
+            id: shootState
+            name: "shoot"
+            source: "../gfx/bomb-action.png"
+            frameCount: 6
+            frameDuration: 155
+            to: { "dying" : 1 } // So that if it takes a frame to clean up, it is on the last frame of the explosion
+        }
+
+        Sprite {
+            name: "dying"
+            source: "../gfx/bomb-action.png"
+            frameCount: 1
+            frameX: 64 * 5
+            frameWidth: 64
+            frameHeight: 64
+            frameDuration: 155
+        }
+
+        SequentialAnimation on x {
+            loops: Animation.Infinite
+            NumberAnimation { from: x; to: x + 4; duration: 900; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: x + 4; to: x; duration: 900; easing.type: Easing.InOutQuad }
+        }
+        SequentialAnimation on y {
+            loops: Animation.Infinite
+            NumberAnimation { from: y; to: y - 4; duration: 900; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: y - 4; to: y; duration: 900; easing.type: Easing.InOutQuad }
+        }
+    }
+}
diff --git a/content/towers/Factory.qml b/content/towers/Factory.qml
new file mode 100755 (executable)
index 0000000..154b127
--- /dev/null
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "../logic.js" as Logic
+import ".."
+
+TowerBase {
+    id: container
+    rof: 160
+    income: 5
+    SpriteSequence {
+        id: sprite
+        width: 64
+        height: 64
+        interpolate: false
+        goalSprite: ""
+
+        Sprite {
+            name: "idle"
+            source: "../gfx/factory-idle.png"
+            frameCount: 4
+            frameDuration: 200
+        }
+
+        Sprite {
+            name: "action"
+            source: "../gfx/factory-action.png"
+            frameCount: 4
+            frameDuration: 90
+            to: { "idle" : 1 }
+        }
+
+        SequentialAnimation on x {
+            loops: Animation.Infinite
+            NumberAnimation { from: x; to: x + 4; duration: 900; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: x + 4; to: x; duration: 900; easing.type: Easing.InOutQuad }
+        }
+        SequentialAnimation on y {
+            loops: Animation.Infinite
+            NumberAnimation { from: y; to: y - 4; duration: 900; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: y - 4; to: y; duration: 900; easing.type: Easing.InOutQuad }
+        }
+    }
+
+    SoundEffect {
+        id: actionSound
+        source: "../audio/factory-action.wav"
+    }
+
+    function fire() {
+        actionSound.play()
+        sprite.jumpTo("action")
+        coinLaunch.start()
+    }
+
+    function spawn() {
+        coin.target = Logic.gameState.mapToItem(container, 240, -32)
+    }
+
+    Image {
+        id: coin
+        property var target: { "x" : 0, "y" : 0 }
+        source: "../gfx/currency.png"
+        visible: false
+    }
+
+    SequentialAnimation {
+        id: coinLaunch
+        PropertyAction { target: coin; property: "visible"; value: true }
+        ParallelAnimation {
+            NumberAnimation { target: coin; property: "x"; from: 16; to: coin.target.x }
+            NumberAnimation { target: coin; property: "y"; from: 16; to: coin.target.y }
+        }
+        PropertyAction { target: coin; property: "visible"; value: false }
+    }
+}
diff --git a/content/towers/Melee.qml b/content/towers/Melee.qml
new file mode 100755 (executable)
index 0000000..ee2621f
--- /dev/null
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import ".."
+
+TowerBase {
+    hp: 4
+    range: 0.1
+    damage: 1
+    rof: 40
+    income: 0
+
+    SpriteSequence {
+        id: sprite
+        width: 64
+        height: 64
+        interpolate: false
+        goalSprite: ""
+
+        Sprite {
+            name: "idle"
+            source: "../gfx/melee-idle.png"
+            frameCount: 8
+            frameDuration: 250
+        }
+
+        Sprite {
+            name: "shoot"
+            source: "../gfx/melee-action.png"
+            frameCount: 2
+            frameDuration: 200
+            to: { "idle" : 1 }
+        }
+    }
+
+    function fire() {
+        shootSound.play()
+        sprite.jumpTo("shoot")
+    }
+
+    SoundEffect {
+        id: shootSound
+        source: "../audio/melee-action.wav"
+    }
+}
diff --git a/content/towers/Ranged.qml b/content/towers/Ranged.qml
new file mode 100755 (executable)
index 0000000..9a4180f
--- /dev/null
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "../logic.js" as Logic
+import ".."
+
+TowerBase {
+    id: container
+    hp: 2
+    range: 6
+    damage: 0 // By projectile
+    rof: 40
+    income: 0
+    property var targetMob
+    property real realDamage: 1
+    function fire() {
+        proj.x = 32 - proj.width / 2
+        proj.y = 0
+        targetMob = Logic.gameState.mobs[col][0]
+        projAnim.to = targetMob.y - container.y -10
+        projAnim.start()
+        shootSound.play()
+        sprite.jumpTo("shoot")
+    }
+
+    Image {
+        id: proj
+        y: 1000
+        SequentialAnimation on y {
+            id: projAnim
+            running: false
+            property real to: 1000
+            SmoothedAnimation {
+                to: projAnim.to
+                velocity: 400
+            }
+            ScriptAction {
+                script: {
+                    if (targetMob && targetMob.hit) {
+                        targetMob.hit(realDamage)
+                        targetMob.inked()
+                        projSound.play()
+                    }
+                }
+            }
+            PropertyAction {
+                value: 1000;
+            }
+        }
+        source: "../gfx/projectile.png"
+    }
+
+    SoundEffect {
+        id: shootSound
+        source: "../audio/shooter-action.wav"
+    }
+    SoundEffect {
+        id: projSound
+        source: "../audio/projectile-action.wav"
+    }
+
+    SpriteSequence {
+        id: sprite
+        width: 64
+        height: 64
+        interpolate: false
+        goalSprite: ""
+
+        Sprite {
+            name: "idle"
+            source: "../gfx/shooter-idle.png"
+            frameCount: 4
+            frameDuration: 250
+        }
+
+        Sprite {
+            name: "shoot"
+            source: "../gfx/shooter-action.png"
+            frameCount: 5
+            frameDuration: 90
+            to: { "idle" : 1 }
+        }
+
+        SequentialAnimation on x {
+            loops: Animation.Infinite
+            NumberAnimation { from: x; to: x - 4; duration: 900; easing.type: Easing.InOutQuad }
+            NumberAnimation { from: x - 4; to: x; duration: 900; easing.type: Easing.InOutQuad }
+        }
+    }
+}
diff --git a/content/towers/TowerBase.qml b/content/towers/TowerBase.qml
new file mode 100755 (executable)
index 0000000..127f2ee
--- /dev/null
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+    property real hp: 1
+    property real range: 0
+    property real damage: 0
+    property int rof: 100
+    property int fireCounter: 0
+    property int income: 0
+    property int row: 0
+    property int col: 0
+
+    width: parent ? parent.squareSize : 0
+    height: parent ? parent.squareSize : 0
+    //This is how it is placed on the gameboard, do not modify/animate the X/Y/Z of a TowerBase please
+    x: col * width
+    y: row * height
+    z: 1000
+
+    function fire() { }
+    function spawn() { } //After all game properties are set
+    function die() { stdDeath.start(); destroy(1000); }
+    function sell() { destroy(); }
+
+    SequentialAnimation on opacity {
+        id: stdDeath
+        running: false
+        loops: 2
+        NumberAnimation { from: 1; to: 0; }
+        NumberAnimation { from: 0; to: 1; }
+    }
+}
diff --git a/disp_obj.cpp b/disp_obj.cpp
new file mode 100755 (executable)
index 0000000..7bbc3dc
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * 
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+/* This file defines the functions to deal with the DSS engine via QT eglfs_kms QPA 
+*  It secures the hardware plane for overlay need, set one time the display proerpties 
+*  of the overlay plane, also sets the primary plane properties for alphablending, 
+*  exports user allocated video buffers to the DRM, queue and dequeue the video buffers
+*  submitted to the QPA 
+*/
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <xf86drmMode.h>
+#include <unistd.h>
+#include "disp_obj.h"
+#include "error.h"
+#include <sys/time.h>
+
+static void page_flip_handler(void *data){
+    bool *page_flipped = (bool *)data; 
+       //MSG("received notification from QPA\n");
+    *page_flipped = true;
+}
+
+DispObj::DispObj(QpaCtlObj *qpa_ctl, void *screen, uint32_t x, 
+                 uint32_t y, uint32_t w, uint32_t h, uint32_t num_planes) {
+    m_screen =  screen;
+    m_crtc_x = x;
+    m_crtc_y = y;
+    m_crtc_w = w;
+    m_crtc_h = h;
+    m_num_planes = num_planes;
+    m_page_flipped = false;
+
+    m_qpa_ctl = qpa_ctl;
+
+    //If display is not connected, don't create overlay planes
+    if(screen != NULL){
+
+        //Secure DSS hardware planes for overlay from QT QPA
+        for(uint32_t i = 0; i < m_num_planes; i++){
+            m_plane_id[i] = m_qpa_ctl->m_create_plane(m_screen);
+        }
+    
+        /* Pass callback function pointer to the QT eglfs_kms QPA. The QPA will
+         call this function to notify display completion of the overlay buffer */
+        m_qpa_ctl->m_set_user_call_back(m_screen, &page_flip_handler, &m_page_flipped);
+    }
+}
+
+DispObj::~DispObj(){
+    for(uint32_t i = 0; i < m_num_planes; i++){
+        m_qpa_ctl->m_distroy_plane(m_screen, m_plane_id[i]);
+    }
+}
+
+/*
+* Set up the DSS for scaling of video planes and blending it with graphics planes
+*/
+int DispObj::set_properties(uint32_t src_w, uint32_t src_h, 
+    uint32_t fb_id, uint32_t plane_idx){
+
+    char trans_key_mode = 2;
+    char *propname[11];
+    unsigned int propval[11];
+    int i;
+
+    for(i = 0; i < 11; i++)
+    {
+        propname[i]= (char *) malloc(sizeof(char)*128);
+    }
+
+    /*set primary/graphics plane property for alpha blending*/
+    strcpy(propname[0],"trans-key-mode");
+    strcpy(propname[1],"alpha_blender");
+    strcpy(propname[2],"zorder");
+
+    propval[0] = trans_key_mode;
+    propval[1] = 1;
+    propval[2] = 1;
+
+    m_qpa_ctl->m_set_plane_properties(m_screen, DRM_PLANE_TYPE_PRIMARY, 0, 
+        3, (const char**)propname, propval);
+
+    /* Set overlay plane properties for input and output resolution (scaling) */
+    /* CRTC properties below are the DSS processed/displayed output proerties */
+    /* and SRC is for input */
+    strcpy(propname[0], "CRTC_X"); //output offset X to be displayed from
+    propval[0] = m_crtc_x;
+    strcpy(propname[1], "CRTC_Y"); //output offset Y to be displayed from
+    propval[1] = m_crtc_y;
+    strcpy(propname[2], "CRTC_W"); //output width, set to screen width in this example
+    propval[2] = m_crtc_w;
+    strcpy(propname[3], "CRTC_H"); //output width, set to screen height in this example
+    propval[3] = m_crtc_h;
+    strcpy(propname[4], "SRC_X"); //input buffer offset X to be processed from
+    propval[4] = 0;
+    strcpy(propname[5], "SRC_Y"); //input buffer offset Y to be processed from
+    propval[5] = 0;
+    strcpy(propname[6], "SRC_W"); //input buffer width
+    propval[6] = src_w << 16 ;
+    strcpy(propname[7], "SRC_H"); //input buffer height
+    propval[7] = src_h << 16;
+    strcpy(propname[8], "zorder"); //order of the video plane when laying on top/below other planes
+    propval[8] = 2;                // higher the value, higher in order the plane reside. Max value is 3
+    strcpy(propname[9], "FB_ID");
+    propval[9] = fb_id;            //frame buffer id
+    strcpy(propname[10], "global_alpha");
+    propval[10] = 150;             //Alpha value for blending
+
+    /* Set the plane properties once. After that only set those properties that changes each time a frame is 
+    displayed - like fb_id. */
+    m_qpa_ctl->m_set_plane_properties(m_screen, DRM_PLANE_TYPE_OVERLAY, m_plane_id[plane_idx], 
+        11, (const char**)propname, propval);
+
+    for (i = 0; i < 11; i++){
+        free(propname[i]);
+    }
+
+    return 0;
+}
+
+/* Export user allocated buffer to the QT QPA/DRM device */
+int DispObj::export_buf2_qpa(uint32_t w, uint32_t h, uint32_t pix_fmt, 
+        uint32_t *pitches, uint32_t *offset, uint32_t fd, uint32_t *fb_id){
+    return m_qpa_ctl->m_export_buffer(m_screen, w, h, pix_fmt, pitches, offset, fd, fb_id);
+}
+
+/* Queue the video buffer to be overlayed to QPA */
+int DispObj::queue_buf(uint32_t plane_idx, uint32_t fb_id){
+    m_qpa_ctl->m_queue_buffer(m_screen, plane_idx, fb_id);
+    return 0;
+}
+
+// Single wait for all the planes submitted to one display as they all get displayed together  
+int DispObj::dequeue_bufs(int wait_time){
+    struct timeval start, now;
+    gettimeofday(&start, NULL);
+
+    if(!wait_time){
+        wait_time = 60; //by default, wait for 60 ms
+    }
+       //MSG("before m_page_flipped = %d", m_page_flipped);
+       do{
+               if (m_page_flipped == false){
+                       usleep(500);
+               }
+               else{
+                       m_page_flipped = false;
+                       return 0;
+               }
+               gettimeofday(&now, NULL);
+       }while(((now.tv_usec - start.tv_usec)/1000) < wait_time);
+       //MSG("after m_page_flipped = %d", m_page_flipped);
+    MSG("Waited for %d msec. Overlay buffer wasn't freed\n", wait_time);
+    return -1;
+}
+
+int DispObj::start_disp(){
+    return(m_qpa_ctl->m_start_disp_plane(m_screen));
+}
diff --git a/disp_obj.h b/disp_obj.h
new file mode 100755 (executable)
index 0000000..8ee91ee
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+#ifndef DISP_OBJ_H
+#define DISP_OBJ_H
+
+#include "qpa_ctl.h"
+
+//Max HW planes on AM57x DSS is 4. One owned by primary and 3 remianed for overlays
+#define MAX_OVERLAY_PLANE 3
+
+class DispObj{
+public: 
+    DispObj(QpaCtlObj *qpa_ctl, void *screen, uint32_t x, 
+        uint32_t y, uint32_t w, uint32_t h, uint32_t num_planes);
+    ~DispObj();
+    int set_properties(uint32_t src_w, uint32_t src_h, 
+        uint32_t fb_id, uint32_t plane_idx);
+    int export_buf2_qpa(uint32_t w, uint32_t h, uint32_t pix_fmt, 
+        uint32_t *pitches, uint32_t *offset, uint32_t fd, uint32_t *fb_id);
+    int queue_buf(uint32_t plane_idx, uint32_t fb_id);
+    int dequeue_bufs(int wait_time);
+    int start_disp();
+private:
+    QpaCtlObj *m_qpa_ctl;
+    void *m_screen;
+    uint32_t m_crtc_x;
+    uint32_t m_crtc_y;
+    uint32_t m_crtc_w;
+    uint32_t m_crtc_h;
+    uint32_t m_num_planes;
+       bool m_page_flipped;
+    uint32_t m_plane_id[MAX_OVERLAY_PLANE];
+};
+
+#endif // DISP_OBJ_H
diff --git a/error.h b/error.h
new file mode 100755 (executable)
index 0000000..4cc1eee
--- /dev/null
+++ b/error.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef ERROR_H
+#define ERROR_H
+
+#include <stdio.h>
+#include <errno.h>
+
+#define ERROR(fmt, ...) \
+    do { fprintf(stderr, "ERROR:%s %s:%d: " fmt "\n", __FILE__, __func__, __LINE__,\
+##__VA_ARGS__); } while (0)
+
+#define MSG(fmt, ...) \
+    do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while (0)
+
+#endif // ERROR_H
diff --git a/gc320.cpp b/gc320.cpp
new file mode 100755 (executable)
index 0000000..fee3c54
--- /dev/null
+++ b/gc320.cpp
@@ -0,0 +1,383 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+/* This file defines the function to program the GC320 IP */
+
+#include <stdint.h>
+#include "cmem_buf.h"
+#include "gc320.h"
+#include "error.h"
+#include "cmem_buf.h"
+
+/* Configure one time the source and destination surface context for all buffers 
+* as they cost some performance overhead if configured per frame. Since the
+* buffer parameters aren't changing in this application run time, we can save the overhead 
+*/
+Gc320Obj::Gc320Obj(uint32_t num_src_surf, uint32_t num_dst_surf, BufObj *src_bo, BufObj *dst_bo){
+    m_dst_width   = dst_bo->m_width;
+    m_dst_height  = dst_bo->m_height;
+    m_dst_stride  = dst_bo->m_stride; 
+    m_dst_format  = gcvSURF_UYVY; 
+
+    m_src_width  = src_bo->m_width;
+    m_src_height = src_bo->m_height;
+    m_src_stride = src_bo->m_stride;
+    m_src_format = gcvSURF_UYVY;
+
+    m_src_surf_ctxt = (surf_context *) malloc(num_src_surf * sizeof(surf_context));
+    m_dst_surf_ctxt = (surf_context *) malloc(num_src_surf * sizeof(surf_context));
+
+    init_gc320();
+
+    configure_surface(m_src_surf_ctxt, num_src_surf, src_bo, m_src_format);
+    configure_surface(m_dst_surf_ctxt, num_dst_surf, dst_bo, m_dst_format);
+}
+
+
+/*
+*  ~Gc320Obj() //Class destructor
+* free all resources
+*/
+Gc320Obj::~Gc320Obj(){
+    if (m_hal != gcvNULL){
+        gcoHAL_Commit(m_hal, true);
+    }
+
+    for(uint32_t i = 0; i < m_num_dst_ctx; i++){
+        if (m_dst_surf_ctxt[i].surf != gcvNULL){
+            gceHARDWARE_TYPE type;
+
+            gcoHAL_GetHardwareType(gcvNULL, &type);
+
+            gcmVERIFY_OK(gcoSURF_Unlock(m_dst_surf_ctxt[i].surf, gcvNULL));
+            gcmVERIFY_OK(gcoSURF_Destroy(m_dst_surf_ctxt[i].surf));
+            gcmVERIFY_OK(gcoHAL_Commit(gcvNULL, true));
+
+            gcoHAL_SetHardwareType(gcvNULL, type);
+        }
+    }
+
+    for(uint32_t i = 0; i < m_num_src_ctx; i++){
+        if (m_src_surf_ctxt[i].surf != gcvNULL){
+            gceHARDWARE_TYPE type;
+
+            gcoHAL_GetHardwareType(gcvNULL, &type);
+
+            gcmVERIFY_OK(gcoSURF_Unlock(m_src_surf_ctxt[i].surf, gcvNULL));
+            gcmVERIFY_OK(gcoSURF_Destroy(m_src_surf_ctxt[i].surf));
+            gcmVERIFY_OK(gcoHAL_Commit(gcvNULL, true));
+
+            gcoHAL_SetHardwareType(gcvNULL, type);
+        }
+    }
+
+    if (m_hal != gcvNULL){
+        gcoHAL_Commit(m_hal, true);
+        gcoHAL_Destroy(m_hal);
+    }
+
+    if (m_os != gcvNULL){
+        gcoOS_Destroy(m_os);
+    }
+}
+
+
+int Gc320Obj::chip_check(){
+    gceSTATUS status;
+    uint32_t i;
+    int ret = 0;
+    gceCHIPMODEL    chip_model;
+    uint32_t       chip_revision;
+    uint32_t       patch_revision;
+    uint32_t       chip_features;
+    uint32_t       chip_minor_features_number;
+    uint32_t       chip_minor_features[MAX_MINORFEATURE_NUMBER];
+
+    status = gcoHAL_QueryChipIdentity(m_hal, &chip_model, &chip_revision, &chip_features, gcvNULL);
+    if (status < 0){
+        ERROR("Failed to query chip info (status = 0x%x)\n", status);
+        ret = -1;
+        goto EXIT;
+    }
+
+    status = gcoOS_ReadRegister(m_os, 0x98, &patch_revision);
+    if (status < 0){
+        ERROR("Failed to read patch version (status = 0x%x)\n", status);
+        ret = -2;
+        goto EXIT;
+    }
+
+    MSG("=================== Chip Information ==================\n");
+    MSG("Chip : GC%x\n", chip_model);
+    MSG("Chip revision: 0x%08x\n", chip_revision);
+    MSG( "Patch revision: 0x%08x\n", patch_revision);
+    MSG("Chip Features: 0x%08x\n", chip_features);
+
+    status = gcoHAL_QueryChipMinorFeatures(m_hal, &chip_minor_features_number, gcvNULL);
+    if (status < 0){
+        ERROR("Failed to query minor feature count (status = 0x%x)\n", status);
+        ret = -2;
+        goto EXIT;
+    }
+
+    if (MAX_MINORFEATURE_NUMBER < chip_minor_features_number){
+        ERROR("no enough space for minor features\n");
+        ret = -3;
+        goto EXIT;
+    }
+
+    status = gcoHAL_QueryChipMinorFeatures(m_hal, &chip_minor_features_number, chip_minor_features);
+    if (status < 0){
+        ERROR("Failed to query minor features (status = 0x%x)\n", status);
+        ret = -4;
+        goto EXIT;
+    }
+
+    for (i = 0; i < chip_minor_features_number; i++){
+        MSG("Chip MinorFeatures%d: 0x%08x\n", i, chip_minor_features[i]);
+    }
+
+    MSG("=======================================================\n");
+
+EXIT:
+
+    return ret;
+}
+
+int Gc320Obj::init_gc320() {
+
+    gceSTATUS status;
+
+    /* Construct the gcoOS object. */
+    status = gcoOS_Construct(gcvNULL, &m_os);
+    if (status < 0){
+        ERROR("Failed to construct OS object (status = %d)\n", status);
+        return false;
+    }
+
+    /* Construct the gcoHAL object. */
+    status = gcoHAL_Construct(gcvNULL, m_os, &m_hal);
+    if (status < 0){
+        ERROR("Failed to construct GAL object (status = %d)\n", status);
+        return false;
+    }
+
+    if (!gcoHAL_IsFeatureAvailable(m_hal, gcvFEATURE_2DPE20)){
+
+        switch (m_dst_format){
+            /* PE1.0 support. */
+        case gcvSURF_X4R4G4B4:
+        case gcvSURF_A4R4G4B4:
+        case gcvSURF_X1R5G5B5:
+        case gcvSURF_A1R5G5B5:
+        case gcvSURF_X8R8G8B8:
+        case gcvSURF_A8R8G8B8:
+        case gcvSURF_R5G6B5:
+            break;
+
+        default:
+            ERROR("the target format %d is not supported by the hardware.\n",
+                m_dst_format);
+            return false;
+        }
+    }
+
+    status = gcoHAL_Get2DEngine(m_hal, &m_engine2d);
+    MSG("****GC320 m_engine2d = %x\n", (uint32_t) m_engine2d);
+    if (status < 0){
+        ERROR("Failed to get 2D engine object (status = %d)\n", status);
+        return false;
+    }
+
+    if (chip_check() < 0){
+        ERROR("Check chip info failed!\n");
+        return false;
+    }
+
+    return true;
+}
+
+int Gc320Obj::configure_surface(surf_context *surf_ctx,
+        uint32_t num_ctx, BufObj *bo, gceSURF_FORMAT surf_format) {
+
+    gceSTATUS status;
+    gceHARDWARE_TYPE type;
+    unsigned long phys = ~0U;
+
+    gcoHAL_GetHardwareType(gcvNULL, &type);
+
+    for(uint32_t i = 0; i < num_ctx; i++){
+        if (!bo->m_buf[i]) {
+            ERROR("Received null pointer\n");
+            return -1;
+        }
+        /* create a wrapper gcoSURF surface object, because we are mapping the user
+        * allocated buffer pool should be gcvPOOL_USER */
+        status = gcoSURF_Construct(
+            gcvNULL,
+            bo->m_width,
+            bo->m_height,
+            1,
+            gcvSURF_BITMAP,
+            surf_format,
+            gcvPOOL_USER,
+            &surf_ctx[i].surf);
+
+        if (status < 0) {
+            ERROR(" Failed to create gcoSURF object\n");
+            return false;
+        }
+
+        /* calculate the size of the buffer needed. Use gcoSURF_QueryFormat API to
+        * format parameters descriptor - this contains information on format as
+        * needed by the Vivante driver
+        */
+        uint32_t width, height;
+        int stride;
+        gcmONERROR(gcoSURF_GetAlignedSize(surf_ctx[i].surf,
+            &width,
+            &height,
+            &stride));
+
+        if((width != bo->m_width) || (height != bo->m_height) || ((uint32_t) stride != bo->m_stride)){
+            ERROR("Allocated Surf buffer width %d, height %d and stride %d doesn't meet GC320 aligned requirement on width %d, height %d and stride %d\n", 
+               bo->m_width, bo->m_height, bo->m_stride, width, height, stride);
+        }
+
+        uint32_t  p_adr_al;
+        gcmONERROR(gcoSURF_GetAlignment(gcvSURF_BITMAP, surf_format,
+            &p_adr_al,
+                       NULL, //&p_x_al,
+            NULL //&p_y_al)
+                       ));
+
+               if((uint32_t)bo->m_buf[i] % p_adr_al){
+                       ERROR("Buffer passed to GC320 doesn't meet the alignment requirement, GC320 alignment need is %x, received buffer with %x aligned address\n", 
+                               p_adr_al, ((uint32_t)bo->m_buf[i]%p_adr_al));
+               }
+
+        /* Buffer provided meets all the requirement from GC320. 
+               Go ahead and set the underlying buffer */
+        gcmONERROR(gcoSURF_SetBuffer(
+            surf_ctx[i].surf,
+            gcvSURF_BITMAP,
+            surf_format,
+            bo->m_stride,
+            bo->m_buf[i],
+            phys));
+
+        if (status < 0) {
+            ERROR("Failed to set buffer for gcoSURF object\n");
+            return false;
+        }
+
+        /* set window size */
+        gcmONERROR(gcoSURF_SetWindow(surf_ctx[i].surf, 0, 0, bo->m_width, bo->m_height));
+        if (status < 0) {
+            ERROR("Failed to set window for gcoSURF object\n");
+            return false;
+        }
+
+        /* lock surface */
+        gcmONERROR(gcoSURF_Lock(surf_ctx[i].surf, surf_ctx[i].phys_address, &bo->m_buf[i]));
+        if (status < 0) {
+            ERROR("Failed to lock gcoSURF object\n");
+            return false;
+        }
+
+        gcoHAL_SetHardwareType(gcvNULL, type);
+    }
+
+    return true;
+
+OnError:
+    ERROR("Failed: %s\n", gcoOS_DebugStatus2Name(status));
+
+    return false;
+}
+
+bool Gc320Obj::rotation_90deg(uint32_t src_surf_indx, uint32_t dst_surf_indx){
+
+    gcsRECT src_rect, dst_rect, clip_rect;
+    gceSTATUS status = gcvSTATUS_OK;
+
+    // render to dest surface
+    // blit with 90 rotation
+    src_rect.left   = 0;
+    src_rect.top    = 0;
+    src_rect.right  = m_src_width;
+    src_rect.bottom = m_src_height;
+
+    // set the clipping according to the rotation
+    clip_rect.left       = 0;
+    clip_rect.top        = 0;
+    clip_rect.right   = m_dst_height;
+    clip_rect.bottom  = m_dst_width;
+
+    gcmONERROR(gco2D_SetClipping(m_engine2d, &clip_rect));
+
+       //Since the buffer is getting rotated 90 degree, make sure the destination buffer width is larger than source buffer height */
+    dst_rect.left   = 0;
+    dst_rect.top    = (m_dst_width - m_src_height);
+    dst_rect.right  = dst_rect.left + m_src_width;
+    dst_rect.bottom = dst_rect.top + m_src_height;
+
+    gcmONERROR(gco2D_SetGenericSource(m_engine2d,
+        m_src_surf_ctxt[src_surf_indx].phys_address, 1, &m_src_stride, 1,
+        gcvLINEAR, m_src_format, gcvSURF_0_DEGREE,
+        m_src_width, m_src_height));
+
+    gcmONERROR(gco2D_SetSource(m_engine2d, &src_rect));
+
+    gcmONERROR(gco2D_SetTarget(m_engine2d,
+        m_dst_surf_ctxt[dst_surf_indx].phys_address[0],
+        m_dst_stride,
+        gcvSURF_90_DEGREE,
+        m_dst_width));
+
+    gcmONERROR(gco2D_Blit(m_engine2d,
+        1,
+        &dst_rect,
+        0xCC,
+        0xCC,
+        m_dst_format));
+    gcmONERROR(gco2D_Flush(m_engine2d));
+    gcmONERROR(gcoHAL_Commit(m_hal, true));
+
+    return true;
+
+OnError:
+    ERROR("Failed: %s\n", gcoOS_DebugStatus2Name(status));
+       return false;
+}
diff --git a/gc320.h b/gc320.h
new file mode 100755 (executable)
index 0000000..399d9cb
--- /dev/null
+++ b/gc320.h
@@ -0,0 +1,122 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef GC320_H
+#define GC320_H
+
+#include <gc_hal.h>
+#include <gc_hal_raster.h>
+
+#define MAX_MINORFEATURE_NUMBER 10
+
+struct surf_context{
+    gcoSURF surf;
+    uint32_t phys_address[4];
+};
+
+/// Uncomment to enable more debugging prints
+#define DEBUG_GC320
+
+class Gc320Obj
+{
+
+public:
+
+    /// Constructor
+    Gc320Obj(uint32_t num_src_surf, uint32_t num_dst_surf, BufObj *src_bo, BufObj *dst_bo);
+    ~Gc320Obj();
+
+    /**
+    * gc320 configure_src_surface()     * Purpose: Construct source surface
+    *
+    * @return Return bool success or failure
+    */
+    int configure_surface(surf_context *surf_ctx, uint32_t num_ctx, BufObj *bo, gceSURF_FORMAT surf_format);
+
+    /**
+    * gc320 render_90degree_rotation()
+    * Purpose: Program GC320 to rotate the  surface 90 degree
+    *
+    * @param index to source surface
+    * @param index to desitination surface
+    *
+    * @return bool true/success or false/failure
+    */
+    bool rotation_90deg(uint32_t a, uint32_t b);
+
+
+private:
+
+    /**
+    * gc320 chip_check()
+    * Purpose: Checkout the GC320 Hardware and print info on it
+    *
+    *
+    * @return 0 on success < 0 on failure
+    */
+    int chip_check();
+
+
+    /**
+    * gc320 initGC30Hardware()
+    * Purpose: Probe and initialize the GC320 Chip
+    *
+    * @return 0 on Success and -1 on Failure
+    */
+    int init_gc320();
+
+    // Runtime parameters
+    gcoOS           m_os;
+    gcoHAL          m_hal;
+    gco2D           m_engine2d;
+
+    /* Dest surface. */
+    gceSURF_FORMAT m_dst_format;
+    uint32_t      m_dst_width;
+    uint32_t      m_dst_height;
+    uint32_t      m_dst_stride;
+    surf_context  *m_dst_surf_ctxt;
+    uint32_t       m_num_dst_ctx;
+
+    /* Source surface. */
+    gceSURF_FORMAT m_src_format;
+    uint32_t      m_src_width;
+    uint32_t      m_src_height;
+    uint32_t      m_src_stride;
+    surf_context  *m_src_surf_ctxt;
+    uint32_t       m_num_src_ctx;
+};
+
+#endif // GC320_H
+
diff --git a/loopback.c b/loopback.c
deleted file mode 100644 (file)
index 0579136..0000000
+++ /dev/null
@@ -1,1139 +0,0 @@
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <malloc.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <stdbool.h>
-#include <linux/videodev2.h>
-#include <omap_drm.h>
-#include <omap_drmif.h>
-#include <xf86drmMode.h>
-#include "loopback.h"
-
-#define ERROR(fmt, ...) \
-       do { fprintf(stderr, "ERROR:%s:%d: " fmt "\n", __func__, __LINE__,\
-##__VA_ARGS__); } while (0)
-
-#define MSG(fmt, ...) \
-       do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while (0)
-
-/* Dynamic debug. */
-#define DBG(fmt, ...) \
-       do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while (0)
-
-/* align x to next highest multiple of 2^n */
-#define ALIGN2(x,n)   (((x) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1))
-#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | \
-       ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | \
-       ((uint32_t)(uint8_t)(d) << 24 ))
-#define FOURCC_STR(str)    FOURCC(str[0], str[1], str[2], str[3])
-
-#define PAGE_SHIFT 12
-#define NBUF (3)
-#define MAX_DRM_PLANES 5
-#define CAP_WIDTH 800
-#define CAP_HEIGHT 600
-#define PIP_POS_X  25
-#define PIP_POS_Y  25
-#define MAX_ZORDER_VAL 3 //For AM57x device, max zoder value is 3
-
-struct control status;
-
-struct dmabuf_buffer {
-       uint32_t fourcc, width, height;
-       int nbo;
-       struct omap_bo *bo[4];
-       uint32_t pitches[4];
-       int fd[4];              /* dmabuf */
-       unsigned fb_id;
-};
-
-struct connector_info {
-       unsigned int id;
-       char mode_str[64];
-       drmModeModeInfo *mode;
-       drmModeEncoder *encoder;
-       int crtc;
-       int pipe;
-};
-
-/*
-* drm output device structure declaration
-*/
-struct drm_device_info
-{
-       int fd;
-       int width;
-       int height;
-       char dev_name[9];
-       char name[4];
-       unsigned int bo_flags;
-       struct dmabuf_buffer **buf[2];
-       struct omap_device *dev;
-       unsigned int crtc_id;
-       unsigned int plane_id[2];
-       unsigned int prop_fbid;
-       unsigned int prop_crtcid;
-       uint64_t zorder_val_primary_plane;
-       uint64_t trans_key_mode_val;
-       uint32_t zorder_val[MAX_DRM_PLANES-1];
-} drm_device;
-
-/*
-* V4L2 capture device structure declaration
-*/
-struct v4l2_device_info {
-       int type;
-       int fd;
-       enum v4l2_memory memory_mode;
-       unsigned int num_buffers;
-       int width;
-       int height;
-       char dev_name[12];
-       char name[10];
-
-       struct v4l2_buffer *buf;
-       struct v4l2_format fmt;
-       struct dmabuf_buffer **buffers;
-} cap0_device, cap1_device;
-
-static volatile int waiting_for_flip;
-
-static struct omap_bo *alloc_bo(struct drm_device_info *device, unsigned int bpp,
-                                                               unsigned int width, unsigned int height,
-                                                               unsigned int *bo_handle, unsigned int *pitch)
-{
-       struct omap_bo *bo;
-       unsigned int bo_flags = device->bo_flags;
-
-       bo_flags |= OMAP_BO_WC;
-       bo = omap_bo_new(device->dev, width * height * bpp / 8, bo_flags);
-
-       if (bo) {
-               *bo_handle = omap_bo_handle(bo);
-               *pitch = width * bpp / 8;
-               if (bo_flags & OMAP_BO_TILED)
-                       *pitch = ALIGN2(*pitch, PAGE_SHIFT);
-       }
-
-       return bo;
-}
-
-//You can use DRM ioctl as well to allocate buffers (DRM_IOCTL_MODE_CREATE_DUMB)
-//and drmPrimeHandleToFD() to get the buffer descriptors
-static struct dmabuf_buffer *alloc_buffer(struct drm_device_info *device,
-                                                                                 unsigned int fourcc, unsigned int w,
-                                                                                 unsigned int h)
-{
-       struct dmabuf_buffer *buf;
-       unsigned int bo_handles[4] = {0}, offsets[4] = {0};
-       int ret;
-
-       buf = (struct dmabuf_buffer *) calloc(1, sizeof(struct dmabuf_buffer));
-       if (!buf) {
-               ERROR("allocation failed");
-               return NULL;
-       }
-
-       buf->fourcc = fourcc;
-       buf->width = w;
-       buf->height = h;
-       buf->nbo = 1;
-       buf->bo[0] = alloc_bo(device, 16, buf->width, buf->height,
-               &bo_handles[0], &buf->pitches[0]);
-
-       ret = drmModeAddFB2(device->fd, buf->width, buf->height, fourcc,
-               bo_handles, buf->pitches, offsets, &buf->fb_id, 0);
-
-       if (ret) {
-               ERROR("drmModeAddFB2 failed: %s (%d)", strerror(errno), ret);
-               return NULL;
-       }
-
-       return buf;
-}
-
-void free_vid_buffers(struct dmabuf_buffer **buf, unsigned int n)
-{
-       unsigned int i;
-
-       if (buf == NULL) return;
-       for (i = 0; i < n; i++) {
-               if (buf[i]) {
-                       close(buf[i]->fd[0]);
-                       omap_bo_del(buf[i]->bo[0]);
-                       free(buf[i]);
-               }
-       }
-       free(buf);
-}
-
-
-static struct dmabuf_buffer **get_vid_buffers(struct drm_device_info *device,
-                                                                                         unsigned int n,
-                                                                                         unsigned int fourcc, unsigned int w, unsigned int h)
-{
-       struct dmabuf_buffer **bufs;
-       unsigned int i = 0;
-
-       bufs = (struct dmabuf_buffer **) calloc(n, sizeof(*bufs));
-       if (!bufs) {
-               ERROR("allocation failed");
-               goto fail;
-       }
-
-       for (i = 0; i < n; i++) {
-               bufs[i] = alloc_buffer(device, fourcc, w, h);
-               if (!bufs[i]) {
-                       ERROR("allocation failed");
-                       goto fail;
-               }
-       }
-       return bufs;
-
-fail:
-       return NULL;
-}
-
-static int v4l2_init_device(struct v4l2_device_info *device)
-{
-       int ret;
-       struct v4l2_capability capability;
-
-       /* Open the capture device */
-       device->fd = open((const char *) device->dev_name, O_RDWR);
-       if (device->fd <= 0) {
-               printf("Cannot open %s device\n", device->dev_name);
-               return -1;
-       }
-
-       MSG("\n%s: Opened Channel\n", device->name);
-
-       /* Check if the device is capable of streaming */
-       if (ioctl(device->fd, VIDIOC_QUERYCAP, &capability) < 0) {
-               perror("VIDIOC_QUERYCAP");
-               goto ERROR;
-       }
-
-       if (capability.capabilities & V4L2_CAP_STREAMING)
-               MSG("%s: Capable of streaming\n", device->name);
-       else {
-               ERROR("%s: Not capable of streaming\n", device->name);
-               goto ERROR;
-       }
-
-       {
-               struct v4l2_streamparm streamparam;
-               streamparam.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               if (ioctl(device->fd, VIDIOC_G_PARM, &streamparam) < 0){
-                       perror("VIDIOC_G_PARM");
-                       goto ERROR;
-               }
-       }
-
-       device->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       ret = ioctl(device->fd, VIDIOC_G_FMT, &device->fmt);
-       if (ret < 0) {
-               ERROR("VIDIOC_G_FMT failed: %s (%d)", strerror(errno), ret);
-               goto ERROR;
-       }
-
-       device->fmt.fmt.pix.pixelformat = FOURCC_STR("YUYV");
-       device->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       device->fmt.fmt.pix.width = device->width;
-       device->fmt.fmt.pix.height = device->height;
-
-       ret = ioctl(device->fd, VIDIOC_S_FMT, &device->fmt);
-       if (ret < 0) {
-               perror("VIDIOC_S_FMT");
-               goto ERROR;
-       }
-
-       MSG("%s: Init done successfully\n", device->name);
-       return 0;
-
-ERROR:
-       close(device->fd);
-
-       return -1;
-}
-
-static void v4l2_exit_device(struct v4l2_device_info *device)
-{
-
-       free(device->buf);
-       close(device->fd);
-
-       return;
-}
-
-
-/*
-* Enable streaming for V4L2 capture device
-*/
-static int v4l2_stream_on(struct v4l2_device_info *device)
-{
-       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       int ret = 0;
-
-       ret = ioctl(device->fd, VIDIOC_STREAMON, &type);
-
-       if (ret) {
-               ERROR("VIDIOC_STREAMON failed: %s (%d)", strerror(errno), ret);
-       }
-
-       return ret;
-}
-
-/*
-* Disable streaming for V4L2 capture device
-*/
-static int v4l2_stream_off(struct v4l2_device_info *device)
-{
-       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       int ret = -1;
-
-       if (device->fd <= 0) {
-               return ret;
-       }
-
-       ret = ioctl(device->fd, VIDIOC_STREAMOFF, &type);
-
-       if (ret) {
-               ERROR("VIDIOC_STREAMOFF failed: %s (%d)", strerror(errno), ret);
-       }
-
-       return ret;
-}
-
-static int v4l2_request_buffer(struct v4l2_device_info *device,
-struct dmabuf_buffer **bufs)
-{
-       struct v4l2_requestbuffers reqbuf;
-       unsigned int i;
-       int ret,dmafd;
-
-       if (device->buf) {
-               // maybe eventually need to support this?
-               ERROR("already reqbuf'd");
-               return -1;
-       }
-
-       reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       reqbuf.memory = device->memory_mode;
-       reqbuf.count = device->num_buffers;
-
-       ret = ioctl(device->fd, VIDIOC_REQBUFS, &reqbuf);
-       if (ret < 0) {
-               ERROR("VIDIOC_REQBUFS failed: %s (%d)", strerror(errno), ret);
-               return ret;
-       }
-
-       if ((reqbuf.count != device->num_buffers) ||
-               (reqbuf.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
-               (reqbuf.memory != V4L2_MEMORY_DMABUF)) {
-                       ERROR("unsupported..");
-                       return -1;
-       }
-
-       device->num_buffers = reqbuf.count;
-       device->buffers = bufs;
-       device->buf = (struct v4l2_buffer *) calloc(device->num_buffers, \
-               sizeof(struct v4l2_buffer));
-       if (!device->buf) {
-               ERROR("allocation failed");
-               return -1;
-       }
-
-       for (i = 0; i < device->num_buffers; i++) {
-               if (bufs[i]->nbo != 1){
-                       ERROR("Number of buffers not right");
-               };
-
-               /* Call omap_bo_dmabuf only once, to export only once
-               * Otherwise, each call will return duplicated fds
-               * This way, every call to omap_bo_dmabuf will return a new fd
-               * Which won't match with any previously exported fds
-               * Instead, store dma fd in buf->fd[] */
-               dmafd = omap_bo_dmabuf(bufs[i]->bo[0]);
-               bufs[i]->fd[0] = dmafd;
-
-               device->buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               device->buf[i].memory = V4L2_MEMORY_DMABUF;
-               device->buf[i].index = i;
-
-               MSG("Exported buffer fd = %d\n", dmafd);
-               ret = ioctl(device->fd, VIDIOC_QUERYBUF, &device->buf[i]);
-               device->buf[i].m.fd = dmafd;
-
-               if (ret) {
-                       ERROR("VIDIOC_QUERYBUF failed: %s (%d)", strerror(errno), ret);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-/*
-* Queue V4L2 buffer
-*/
-static int v4l2_queue_buffer(struct v4l2_device_info *device,
-struct dmabuf_buffer *buf)
-{
-       struct v4l2_buffer *v4l2buf = NULL;
-       int  ret, fd;
-       unsigned char i;
-
-       if(buf->nbo != 1){
-               ERROR("number of bufers not right\n");
-               return -1;
-       }
-
-       fd = buf->fd[0];
-
-       for (i = 0; i < device->num_buffers; i++) {
-               if (device->buf[i].m.fd == fd) {
-                       v4l2buf = &device->buf[i];
-               }
-       }
-
-       if (!v4l2buf) {
-               ERROR("invalid buffer");
-               return -1;
-       }
-       ret = ioctl(device->fd, VIDIOC_QBUF, v4l2buf);
-       if (ret) {
-               ERROR("VIDIOC_QBUF failed: %s (%d)", strerror(errno), ret);
-       }
-
-       return ret;
-}
-
-/*
-* DeQueue V4L2 buffer
-*/
-struct dmabuf_buffer *v4l2_dequeue_buffer(struct v4l2_device_info *device)
-{
-       struct dmabuf_buffer *buf;
-       struct v4l2_buffer v4l2buf;
-       int ret;
-
-       v4l2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       v4l2buf.memory = V4L2_MEMORY_DMABUF;
-       ret = ioctl(device->fd, VIDIOC_DQBUF, &v4l2buf);
-       if (ret) {
-               ERROR("VIDIOC_DQBUF failed: %s (%d)\n", strerror(errno), ret);
-               return NULL;
-       }
-
-       buf = device->buffers[v4l2buf.index];
-
-       device->buf[v4l2buf.index].timestamp = v4l2buf.timestamp;
-       if(buf->nbo != 1){
-               ERROR("num buffers not proper\n");
-               return NULL;
-       }
-
-       return buf;
-}
-
-
-
-unsigned int get_drm_prop_val(int fd, drmModeObjectPropertiesPtr props,
-                                                         const char *name)
-{
-       drmModePropertyPtr p;
-       unsigned int i, prop_id = 0; /* Property ID should always be > 0 */
-
-       for (i = 0; !prop_id && i < props->count_props; i++) {
-               p = drmModeGetProperty(fd, props->props[i]);
-               if (!strcmp(p->name, name)){
-                       prop_id = p->prop_id;
-                       break;
-               }
-               drmModeFreeProperty(p);
-       }
-       if (!prop_id) {
-               printf("Could not find %s property\n", name);
-               drmModeFreeObjectProperties(props);
-               exit(-1);
-       }
-
-       drmModeFreeProperty(p);
-       return props->prop_values[i];
-}
-
-unsigned int find_drm_prop_id(int fd, drmModeObjectPropertiesPtr props,
-                                                         const char *name)
-{
-       drmModePropertyPtr p;
-       unsigned int i, prop_id = 0; /* Property ID should always be > 0 */
-
-       for (i = 0; !prop_id && i < props->count_props; i++) {
-               p = drmModeGetProperty(fd, props->props[i]);
-               if (!strcmp(p->name, name)){
-                       prop_id = p->prop_id;
-                       break;
-               }
-               drmModeFreeProperty(p);
-       }
-       if (!prop_id) {
-               printf("Could not find %s property\n", name);
-               drmModeFreeObjectProperties(props);
-               exit(-1);
-       }
-
-       return prop_id;
-}
-
-void add_property(int fd, drmModeAtomicReqPtr req,
-                                 drmModeObjectPropertiesPtr props,
-                                 unsigned int plane_id,
-                                 const char *name, int value)
-{
-       unsigned int prop_id = find_drm_prop_id(fd, props, name);
-       if(drmModeAtomicAddProperty(req, plane_id, prop_id, value) < 0){
-               printf("failed to add property\n");
-       }
-}
-
-void drm_add_plane_property(struct drm_device_info *dev, drmModeAtomicReqPtr req)
-{
-       unsigned int i;
-       unsigned int crtc_x_val = 0;
-       unsigned int crtc_y_val = 0;
-       unsigned int crtc_w_val = dev->width;
-       unsigned int crtc_h_val = dev->height;
-       drmModeObjectProperties *props;
-       unsigned int zorder_val = 1;
-       unsigned int buf_index;
-       struct v4l2_device_info  *v4l2_device;
-
-       for(i = 0; i < status.num_cams; i++){
-               unsigned int plane_id = dev->plane_id[i];
-
-               if(i) {
-                       crtc_x_val = PIP_POS_X;
-                       crtc_y_val = PIP_POS_Y;
-                       crtc_w_val /= 3;
-                       crtc_h_val /= 3;
-               }
-               props = drmModeObjectGetProperties(dev->fd, plane_id,
-                       DRM_MODE_OBJECT_PLANE);
-
-               if(props == NULL){
-                       ERROR("drm obeject properties for plane type is NULL\n");
-                       exit (-1);
-               }
-
-               //fb id value will be set every time new frame is to be displayed
-               dev->prop_fbid = find_drm_prop_id(drm_device.fd, props, "FB_ID");
-
-               //Will need to change run time crtc id to disable/enable display of plane
-               dev->prop_crtcid = find_drm_prop_id(drm_device.fd, props, "CRTC_ID");
-
-               //storing zorder val to restore it before quitting the demo
-               drm_device.zorder_val[i] = get_drm_prop_val(drm_device.fd, props, "zorder");
-
-               //Set the fb id based on which camera is chosen to be main camera 
-               if (status.main_cam  == 1){
-                       buf_index = (i+1)%2;
-               }
-               else {
-                       buf_index = i;
-               }
-
-               if(buf_index == 0){
-                       v4l2_device = &cap0_device;
-               }
-               else{
-                       v4l2_device = &cap1_device;
-               }
-               printf("w=%d, h=%d\n", v4l2_device->width, v4l2_device->height);
-               add_property(dev->fd, req, props, plane_id, "FB_ID", dev->buf[buf_index][0]->fb_id);
-
-               //set the plane properties once. No need to set these values every time
-               //with the display of frame. 
-               add_property(dev->fd, req, props, plane_id, "CRTC_ID", dev->crtc_id);
-               add_property(dev->fd, req, props, plane_id, "CRTC_X", crtc_x_val);
-               add_property(dev->fd, req, props, plane_id, "CRTC_Y", crtc_y_val);
-               add_property(dev->fd, req, props, plane_id, "CRTC_W", crtc_w_val);
-               add_property(dev->fd, req, props, plane_id, "CRTC_H", crtc_h_val);
-               add_property(dev->fd, req, props, plane_id, "SRC_X", 0);
-               add_property(dev->fd, req, props, plane_id, "SRC_Y", 0);
-               add_property(dev->fd, req, props, plane_id, "SRC_W", v4l2_device->width << 16);
-               add_property(dev->fd, req, props, plane_id, "SRC_H", v4l2_device->height << 16);
-               add_property(dev->fd, req, props, plane_id, "zorder", zorder_val++);
-       }
-}
-
-uint32_t drm_reserve_plane(int fd, unsigned int *ptr_plane_id, int num_planes)
-{
-       unsigned int i;
-       int idx = 0;
-       drmModeObjectProperties *props;
-       drmModePlaneRes *res = drmModeGetPlaneResources(fd);
-       if(res == NULL){
-               ERROR("plane resources not found\n");
-       }
-
-       for (i = 0; i < res->count_planes; i++) {
-               uint32_t plane_id = res->planes[i];
-               unsigned int type_val;
-
-               drmModePlane *plane = drmModeGetPlane(fd, plane_id);
-               if(plane == NULL){
-                       ERROR("plane  not found\n");
-               }
-
-               props = drmModeObjectGetProperties(fd, plane->plane_id, DRM_MODE_OBJECT_PLANE);
-
-               if(props == NULL){
-                       ERROR("plane (%d) properties not found\n",  plane->plane_id);
-               }
-
-               type_val = get_drm_prop_val(fd, props, "type");
-
-               if(type_val == DRM_PLANE_TYPE_OVERLAY){
-                       ptr_plane_id[idx++] = plane_id;
-               }
-
-               drmModeFreeObjectProperties(props);
-               drmModeFreePlane(plane);
-
-               if(idx == num_planes){
-                       drmModeFreePlaneResources(res);
-                       return 0;
-               }
-       }
-
-       ERROR("plane couldn't be reserved\n");
-       return -1;
-}
-
-
-/* Get crtc id and resolution. */
-void drm_crtc_resolution(struct drm_device_info *device)
-{
-       drmModeCrtc *crtc;
-       int i;
-
-       drmModeResPtr res = drmModeGetResources(device->fd);
-
-       if (res == NULL){
-               ERROR("drmModeGetResources failed: %s\n", strerror(errno));
-               exit(0);
-       };
-
-       for (i = 0; i < res->count_crtcs; i++) {
-               unsigned int crtc_id = res->crtcs[i];
-
-               crtc = drmModeGetCrtc(device->fd, crtc_id);
-               if (!crtc) {
-                       DBG("could not get crtc %i: %s\n", res->crtcs[i], strerror(errno));
-                       continue;
-               }
-               if (!crtc->mode_valid) {
-                       drmModeFreeCrtc(crtc);
-                       continue;
-               }
-
-               printf("CRTCs size: %dx%d\n", crtc->width, crtc->height);
-               device->crtc_id = crtc_id;
-               device->width = crtc->width;
-               device->height = crtc->height;
-
-               drmModeFreeCrtc(crtc);
-       }
-
-       drmModeFreeResources(res);
-}
-
-/*
-* DRM restore properties
-*/
-static void drm_restore_props(struct drm_device_info *device)
-{
-       unsigned int i;
-       drmModeObjectProperties *props;
-       int ret;
-
-       drmModeAtomicReqPtr req = drmModeAtomicAlloc();
-
-       props = drmModeObjectGetProperties(device->fd, device->crtc_id,
-               DRM_MODE_OBJECT_CRTC);
-
-       //restore trans-key-mode and z-order of promary plane
-       add_property(device->fd, req, props, device->crtc_id, "trans-key-mode", \
-               device->trans_key_mode_val);
-       add_property(device->fd, req, props, device->crtc_id, "zorder", \
-               device->zorder_val_primary_plane);
-
-       //restore z-order of overlay planes
-       for(i = 0; i < status.num_cams; i++){
-               props = drmModeObjectGetProperties(device->fd, device->plane_id[i],
-                       DRM_MODE_OBJECT_PLANE);
-
-               if(props == NULL){
-                       ERROR("drm obeject properties for plane type is NULL\n");
-                       exit (-1);
-               }
-
-               add_property(device->fd, req, props, device->plane_id[i], \
-                       "zorder", device->zorder_val[i]);
-       }
-
-       //Commit all the added properties
-       ret = drmModeAtomicCommit(device->fd, req, DRM_MODE_ATOMIC_TEST_ONLY, 0);
-       if(!ret){
-               drmModeAtomicCommit(device->fd, req, 0, 0);
-       }
-       else{
-               ERROR("ret from drmModeAtomicCommit = %d\n", ret);
-       }
-
-       drmModeAtomicFree(req);
-}
-
-/*
-* drm device init
-*/
-static int drm_init_device(struct drm_device_info *device)
-{
-       device->fd = status.drm_fd;
-
-       device->dev = omap_device_new(device->fd);
-
-       /* Get CRTC id and resolution. As well set the global display width and height */
-       drm_crtc_resolution(device);
-
-       /* Store display resolution so GUI can be configured */
-       status.display_xres = device->width;
-       status.display_yres = device->height;
-
-       drm_reserve_plane(device->fd, device->plane_id, status.num_cams);
-
-       return 0;
-}
-
-/*
-*Clean resources while exiting drm device
-*/
-static void drm_exit_device(struct drm_device_info *device)
-{
-       drm_restore_props(device);
-       omap_device_del(device->dev);
-       device->dev = NULL;
-
-       return;
-}
-
-/*
-* Set up the DSS for blending of video and graphics planes
-*/
-static int drm_init_dss(void)
-{
-       drmModeObjectProperties *props;
-       int ret;
-       FILE *fp;
-       char str[10];
-       char trans_key_mode = 2;
-
-       /*
-       * Dual camera demo is supported on Am437x and AM57xx evm. Find which
-       * specific SoC the demo is running to set the trans key mode -
-       * found at the corresponding TRM, for example,
-       * For AM437x: trans_key_mode = 1 GFX Dest Trans
-       *             TransKey applies to GFX overlay, marking which
-       *              pixels come from VID overlays)
-       * For AM57xx: trans_key_mode = 2 Source Key.
-       *             Match on Layer4 makes Layer4 transparent (zorder 3)
-       *
-       * The deault mode is 1 for backward compatibility
-       */
-
-       fp = fopen("/proc/sys/kernel/hostname", "r");
-       fscanf(fp, "%s", str);
-
-       //terminate the string after the processor name. "-evm" extension is
-       //ignored in case the demo gets supported on other boards like idk etc
-       str[6] = '\0';
-       printf("Running the demo on %s processor\n", str);
-
-       //Set trans-key-mode to 1 if dual camera demo is running on AM437x
-       if (strcmp(str,"am437x") == 0){
-               trans_key_mode = 1;
-       }
-
-       drmModeAtomicReqPtr req = drmModeAtomicAlloc();
-
-       /* Set CRTC properties */
-       props = drmModeObjectGetProperties(drm_device.fd, drm_device.crtc_id,
-               DRM_MODE_OBJECT_CRTC);
-
-       drm_device.zorder_val_primary_plane = get_drm_prop_val(drm_device.fd,
-               props, "zorder");
-       drm_device.trans_key_mode_val = get_drm_prop_val(drm_device.fd, props,
-               "trans-key-mode");
-
-       add_property(drm_device.fd, req, props, drm_device.crtc_id,
-               "trans-key-mode", trans_key_mode);
-       add_property(drm_device.fd, req, props, drm_device.crtc_id,
-               "alpha_blender", 1);
-       add_property(drm_device.fd, req, props, drm_device.crtc_id,
-               "zorder", MAX_ZORDER_VAL);
-
-       /* Set overlay plane properties like zorder, crtc_id, buf_id, src and */
-       /* dst w, h etc                                                       */
-       drm_add_plane_property(&drm_device, req);
-
-       //Commit all the added properties
-       ret = drmModeAtomicCommit(drm_device.fd, req, DRM_MODE_ATOMIC_TEST_ONLY, 0);
-       if(!ret){
-               drmModeAtomicCommit(drm_device.fd, req, 0, 0);
-       }
-       else{
-               ERROR("ret from drmModeAtomicCommit = %d\n", ret);
-               return -1;
-       }
-
-       drmModeAtomicFree(req);
-       return 0;
-}
-
-
-/*
-* drm disable pip layer
-*/
-void drm_disable_pip(void)
-{
-       int ret;
-       drmModeAtomicReqPtr req = drmModeAtomicAlloc();
-
-       drmModeAtomicAddProperty(req, drm_device.plane_id[1],
-               drm_device.prop_fbid, 0);
-       drmModeAtomicAddProperty(req, drm_device.plane_id[1],
-               drm_device.prop_crtcid, 0);
-
-       ret = drmModeAtomicCommit(drm_device.fd, req,
-               DRM_MODE_ATOMIC_TEST_ONLY, 0);
-       if(!ret){
-               drmModeAtomicCommit(drm_device.fd, req,
-                       0, 0);
-       }
-       else{
-               ERROR("failed to enable plane %d atomically: %s",
-                       drm_device.plane_id[!status.main_cam], strerror(errno));
-       }
-
-       drmModeAtomicFree(req);
-}
-
-void drm_enable_pip(void)
-{
-       int ret;
-
-       drmModeAtomicReqPtr req = drmModeAtomicAlloc();
-
-       drmModeAtomicAddProperty(req, drm_device.plane_id[1],
-               drm_device.prop_fbid, drm_device.buf[!status.main_cam][0]->fb_id);
-       drmModeAtomicAddProperty(req, drm_device.plane_id[1],
-               drm_device.prop_crtcid, drm_device.crtc_id);
-
-       ret = drmModeAtomicCommit(drm_device.fd, req,
-               DRM_MODE_ATOMIC_TEST_ONLY, 0);
-
-       if(!ret){
-               drmModeAtomicCommit(drm_device.fd, req, 0, 0);
-       }
-       else{
-               ERROR("failed to enable plane %d atomically: %s",
-                       drm_device.plane_id[!status.main_cam], strerror(errno));
-       }
-
-       drmModeAtomicFree(req);
-}
-
-
-/*
-* Initialize the app resources with default parameters
-*/
-void default_parameters(void)
-{
-       /* Main camera display */
-       memset(&drm_device, 0, sizeof(drm_device));
-       strcpy(drm_device.dev_name,"/dev/drm");
-       strcpy(drm_device.name,"drm");
-       drm_device.width=0;
-       drm_device.height=0;
-       drm_device.bo_flags = OMAP_BO_SCANOUT;
-       drm_device.fd = 0;
-
-       /* Main camera */
-       cap0_device.memory_mode = V4L2_MEMORY_DMABUF;
-       cap0_device.num_buffers = NBUF;
-       strcpy(cap0_device.dev_name,"/dev/video1");
-       strcpy(cap0_device.name,"Capture 0");
-       cap0_device.buffers = NULL;
-       cap0_device.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-       cap0_device.width = CAP_WIDTH;
-       cap0_device.height = CAP_HEIGHT;
-
-       /* PiP camera */
-       cap1_device.memory_mode = V4L2_MEMORY_DMABUF;
-       cap1_device.num_buffers = NBUF;
-       strcpy(cap1_device.dev_name,"/dev/video0");
-       strcpy(cap1_device.name,"Capture 1");
-       cap1_device.buffers = NULL;
-       cap1_device.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-       cap1_device.width = CAP_WIDTH;
-       cap1_device.height = CAP_HEIGHT;
-
-       /* Set the default parameters for device options */
-       status.main_cam=0;
-       status.num_cams=2;
-       if(status.num_cams == 1){
-               status.pip=false;
-       }
-       else{
-               status.pip=true;
-       }
-       status.exit=false;
-
-       return;
-}
-
-/*
-* Free resource and exit devices
-*/
-void exit_devices(void)
-{
-       v4l2_exit_device(&cap0_device);
-       if (status.num_cams==2) {
-               v4l2_exit_device(&cap1_device);
-       }
-       free_vid_buffers(drm_device.buf[0], NBUF);
-       free_vid_buffers(drm_device.buf[1], NBUF);
-       drm_exit_device(&drm_device);
-}
-
-/*
-* End camera streaming
-*/
-void end_streaming(void)
-{
-       v4l2_stream_off(&cap0_device);
-       if (status.num_cams==2) {
-               v4l2_stream_off(&cap1_device);
-       }
-}
-
-void set_plane_properties()
-{
-       int ret;
-       drmModeAtomicReqPtr req = drmModeAtomicAlloc();
-
-       drmModeAtomicAddProperty(req, drm_device.plane_id[0],
-               drm_device.prop_fbid, drm_device.buf[status.main_cam][0]->fb_id);
-
-       if(status.pip){
-               drmModeAtomicAddProperty(req, drm_device.plane_id[1],
-                       drm_device.prop_fbid, drm_device.buf[!status.main_cam][0]->fb_id);
-       }
-       ret = drmModeAtomicCommit(drm_device.fd, req,
-               DRM_MODE_ATOMIC_TEST_ONLY, 0);
-       if(!ret){
-               drmModeAtomicCommit(drm_device.fd, req,
-                       0, 0);
-       }
-       else{
-               ERROR("failed to enable plane %d atomically: %s",
-                       drm_device.plane_id[!status.main_cam], strerror(errno));
-       }
-       drmModeAtomicFree(req);
-}
-/*
-* Initializes all drm and v4l2 devices for loopback
-*/
-int init_loopback(void)
-{
-       bool status_cam0 = 0;
-       bool status_cam1 = 0;
-
-       /* Declare properties for video and capture devices */
-       default_parameters();
-
-       /* Initialize the drm display devic */
-       if (drm_init_device(&drm_device)) goto Error;
-
-       /* Check to see if the display resolution is very small.  If so, the
-       * camera capture resolution needs to be lowered so that the scaling
-       * limits of the DSS are not reached */
-       if (drm_device.width < 640) {
-               /* Set capture 0 device resolution */
-               cap0_device.width = 640;
-               cap0_device.height = 480;
-
-               /* Set capture 1 device resolution */
-               cap1_device.width = 640;
-               cap1_device.height = 480;
-       }
-
-       /* Initialize the v4l2 capture devices */
-       if (v4l2_init_device(&cap0_device) < 0) {
-               printf("first camera detection failed\n");
-               /* If there is not a second camera, program can still continue */
-               status.num_cams=1;
-               status.main_cam=1;
-               status.pip=false;
-       }
-       else{
-               unsigned int i;
-               struct dmabuf_buffer **buffers = get_vid_buffers(&drm_device, cap0_device.num_buffers, 
-                       cap0_device.fmt.fmt.pix.pixelformat, cap0_device.width, cap0_device.height);
-
-               if (!buffers) {
-                       goto Error;
-               }
-
-               drm_device.buf[0] = buffers;
-
-               /* Pass these buffers to the capture drivers */
-               if (v4l2_request_buffer(&cap0_device, buffers) < 0) {
-                       goto Error;
-               }
-
-               for (i = 0; i < cap0_device.num_buffers; i++) {
-                       v4l2_queue_buffer(&cap0_device, buffers[i]);
-               }
-
-               status_cam0 = 1;
-       }
-
-       if(v4l2_init_device(&cap1_device) < 0) {
-               /* If there is not a second camera, program can still continue */
-               if(status.num_cams ==2){
-                       status.num_cams=1;
-                       status.pip=false;
-                       printf("Only one camera detected\n");
-               }
-               //first camera wasn't detected
-               else if (!status_cam0){
-                       printf("No camera detected\n");
-                       goto Error;
-               }
-       }
-       else{
-               unsigned int i;
-               struct dmabuf_buffer **buffers = get_vid_buffers(&drm_device, cap1_device.num_buffers, 
-                       cap1_device.fmt.fmt.pix.pixelformat, cap1_device.width, cap1_device.height);
-               if (!buffers) {
-                       goto Error;
-               }
-
-               drm_device.buf[1] = buffers;
-
-               /* Pass these buffers to the capture drivers */
-               if (v4l2_request_buffer(&cap1_device, buffers) < 0) {
-                       goto Error;
-               }
-
-               for (i = 0; i < cap1_device.num_buffers; i++) {
-                       v4l2_queue_buffer(&cap1_device, buffers[i]);
-               }
-
-               status_cam1 = 1;
-       }
-
-       /* Enable streaming for the v4l2 capture devices */
-       if(status_cam0){
-               if (v4l2_stream_on(&cap0_device) < 0) goto Error;
-       }
-
-       if (status_cam1) {
-               if (v4l2_stream_on(&cap1_device) < 0) goto Error;
-       }
-
-       /* Configure the DSS to blend video and graphics layers */
-       if (drm_init_dss() < 0 ) goto Error;
-
-       return 0;
-
-Error:
-       status.exit = true;
-       return -1;
-}
-
-static void page_flip_handler(int fd, unsigned int frame,
-                                                         unsigned int sec, unsigned int usec,
-                                                         void *data)
-{
-       int *flip_status = data;
-       *flip_status = 0;
-
-       /* To avoid compile time warning */
-       (void)fd;
-       (void)frame;
-       (void)sec;
-       (void)usec;
-}
-
-static void page_flip_handler_null(int fd, unsigned int frame,
-                                                              unsigned int sec, unsigned int usec,
-                                                              void *data)
-{
-       /* To avoid compile time warning */
-       (void)fd;
-       (void)frame;
-       (void)sec;
-       (void)usec;
-       (void)data;
-}
-
-void process_frame(void)
-{
-       struct dmabuf_buffer *buf[2] = {NULL, NULL};
-       struct v4l2_device_info *v4l2_device[2] =
-       {&cap0_device, &cap1_device};
-
-       /* Request a capture buffer from the driver that can be copied to */
-       /* framebuffer */
-       buf[status.main_cam] =
-               v4l2_dequeue_buffer(v4l2_device[status.main_cam]);
-
-       waiting_for_flip = 1;
-
-       status.drm_plane_sreq_handler(drm_device.plane_id[0],
-               drm_device.prop_fbid,
-               buf[status.main_cam]->fb_id,
-               (status.pip==true)?page_flip_handler_null:
-               page_flip_handler,
-               (void *)&waiting_for_flip);
-
-
-       if (status.pip==true) {
-               buf[!status.main_cam] =
-                       v4l2_dequeue_buffer(v4l2_device[!status.main_cam]);
-
-               status.drm_plane_sreq_handler(drm_device.plane_id[1],
-                       drm_device.prop_fbid,
-                       buf[!status.main_cam]->fb_id,
-                       page_flip_handler,
-                       (void *)&waiting_for_flip);
-       }
-
-
-       while (waiting_for_flip) {
-               usleep(1000);
-       }
-
-       v4l2_queue_buffer(v4l2_device[status.main_cam], buf[status.main_cam]);
-       if(status.pip == true){
-               v4l2_queue_buffer(v4l2_device[!status.main_cam], buf[!status.main_cam]);
-       }
-}
diff --git a/loopback.h b/loopback.h
deleted file mode 100644 (file)
index 0f68f18..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef LOOP
-#define LOOPBACK_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef        void (*drm_page_flip_handler)(int fd,
-               unsigned int sequence,
-               unsigned int tv_sec,
-               unsigned int tv_usec,
-               void *user_data);
-
-typedef int  (*drm_plane_sreq)(uint32_t plane_id,
-               uint32_t prop_fbid,
-               uint32_t buffer_id,
-               drm_page_flip_handler handler,
-               void* user_data);
-
-struct control {
-    unsigned int main_cam;
-    unsigned int num_cams;
-    unsigned int num_jpeg;
-    unsigned int display_xres, display_yres;
-    bool pip;
-    bool jpeg;
-    bool exit;
-    int drm_fd;
-    drm_plane_sreq drm_plane_sreq_handler;
-};
-
-extern struct control status;
-
-int init_loopback(void);
-void process_frame(void);
-void end_streaming(void);
-void exit_devices(void);
-void drm_disable_pip(void);
-void drm_enable_pip(void);
-void set_plane_properties(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // LOOPBACK_H
index 81c7130b07e03a6784812eeca3f7a94d05a8a9a4..c7194dacca383eef2d836d6b0cfebd854d12851f 100644 (file)
--- a/main.cpp
+++ b/main.cpp
-#include <qglobal.h>
-#include <QApplication>
-#include <QLabel>
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
 
-#if QT_VERSION < 0x050000
-#include <QWSServer>
-#endif
+#include <QGuiApplication>
+#include <QQuickView>
+#include <QQmlEngine>
+#include <QQmlContext>
+#include <QScreen>
+#include <QDebug>
+#include "video_graphics_test.h"
 
+QGuiApplication *g_qt_app;
 
-#include <QPushButton>
-#include "mainwindow.h"
+/*
+This application demonstrates the advance processing capabilities of DSS IP when elfs QPA 
+is used to run the QT application. eglfs QPA is used when there is a need for hardware
+accelerated randering of the graphics content drawn by QT. eglfs QPA takes control of the 
+display device and hence application relies on QT QPA to do the advance processing abilities of 
+DSS IP like scaling, alpha blending and overlaying. Along with DSS advance capabilities using QT 
+QPA for hardware accelerated rendering of the graphcis content on SGX, this application also 
+demonstrates video rotation feature using GC320 IP, video capture using VIP interface and 
+displaying these content on two screens. The data flow is as follows
+             ---->GC320 rotate 90 degree --> QT QPA (draws the graphics content from qml file, scale, alpha blend and overlay (on DSS) the video with SGX output)
+                       |
+VIP Capture -
+            |
+             ----> QT QPA (draws the graphics content from qml file, scale, alpha blend and overlay (on DSS) the video with SGX output)
 
-int main(int argc, char *argv[])
+
+*/
+static QQuickView *addView(QScreen *screen, int screenIdx)
 {
-    QApplication a(argc, argv);
-    MainWindow w(NULL, &a);
+    qDebug("Creating new QQuickView for screen %p", screen);
+    QQuickView *v = new QQuickView;
+
+    v->setScreen(screen);
+    v->setResizeMode(QQuickView::SizeViewToRootObject);//SizeRootObjectToView); //
+    v->rootContext()->setContextProperty("screenIdx", screenIdx);
+    v->rootContext()->setContextProperty("screenGeom", screen->geometry());
+    v->rootContext()->setContextProperty("screenAvailGeom", screen->availableGeometry());
+    v->rootContext()->setContextProperty("screenVirtGeom", screen->virtualGeometry());
+    v->rootContext()->setContextProperty("screenAvailVirtGeom", screen->availableVirtualGeometry());
+    v->rootContext()->setContextProperty("screenPhysSizeMm", screen->physicalSize());
+    v->rootContext()->setContextProperty("screenRefresh", screen->refreshRate());
+
+    if (screenIdx == 1){
+        v->setSource(QUrl("qrc:/clocks.qml"));
+    }
+    else{
+               v->setSource(QUrl("qrc:/maroon.qml"));
+    }
+
+    QObject::connect(v->engine(), &QQmlEngine::quit, qGuiApp, &QCoreApplication::quit);
+
+    return v;
+}
+
+int main(int argc, char **argv)
+{
+       //Enable them when need to debug the QPA
+    //qputenv("QT_LOGGING_RULES", "qt.qpa.*=true");
+    //qputenv("QSG_INFO", "1");
+
+    QGuiApplication app(argc, argv);
+    VideoGraphicsThread* video_graphics_test;
+
+    QList<QScreen *> screens = app.screens();
+    qDebug("Application sees %d screens", screens.count());
+    qDebug() << screens;
+
+    QVector<QQuickView *> views;
+       //Set the QML based graphics content to be rendered for each screen
+    for (int i = 0; i < screens.count(); ++i) {
+        QQuickView *v = addView(screens[i], i);
+        views.append(v);
+        v->showFullScreen();
+    }
+
+    g_qt_app=&app;
+
+       //Create and start the thread to capture, rotate and display the content 
+    video_graphics_test = new VideoGraphicsThread;
+    video_graphics_test->start();
 
-#if QT_VERSION < 0x050000
-       QWSServer::setBackground(QBrush(QColor(0, 0, 0, 0)));
-#endif
+    int r = app.exec();
 
-    w.show();
-    return a.exec();
+    qDeleteAll(views);
+    return r;
 }
 
diff --git a/mainwindow.cpp b/mainwindow.cpp
deleted file mode 100644 (file)
index ac2a58e..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-#include "mainwindow.h"
-#include "ui_mainwindow.h"
-#include <QThread>
-#include <QMutex>
-#include "loopback.h"
-#include <stdio.h>
-#include <qpa/qplatformnativeinterface.h>
-
-class MyThread : public QThread
-{
-       Q_OBJECT
-
-protected:
-       void run();
-};
-
-MyThread* loopback;
-QMutex drm_resource;
-
-MainWindow::MainWindow(QWidget *parent, QApplication *a) :
-QMainWindow(parent),
-ui(new Ui::MainWindow)
-{
-       ui->setupUi(this);
-       this->setAttribute(Qt::WA_TranslucentBackground);
-       this->setWindowFlags(Qt::FramelessWindowHint);
-
-       platInf = a->platformNativeInterface();
-       status.drm_fd = (int) platInf->nativeResourceForIntegration("drm_fd");
-       status.drm_plane_sreq_handler = \
-               (drm_plane_sreq)platInf->nativeResourceForIntegration("drm_plane_set_req");
-
-       loopback = new MyThread();
-
-       if(init_loopback() < 0) {
-               /* TODO: make sure exit occurs properly */
-       }
-
-       /* Configure GUI */
-       this->setFixedSize(status.display_xres, status.display_yres);
-       ui->frame->setGeometry(0, 0, status.display_xres, status.display_yres);
-
-       /* Set the back ground color to black */
-       /* This is a workaround required when moving from Qt4 to QT5.  */
-       /* QT5 doesn't support QWSServer. This is causing the graphics */
-       /* windows not to clear up when being instructed to be hidden  */
-       /* Making the background color black solves the problem        */
-       ui->frame->setStyleSheet("background-color:black;");
-       ui->frame->show();
-
-       ui->frame_pip->setGeometry(25, 25, status.display_xres/3, status.display_yres/3);
-       ui->capture->setGeometry(status.display_xres/2 - 210,
-               status.display_yres - 50,
-               91, 41);
-       ui->switch_2->setGeometry(status.display_xres/2 - 100,
-               status.display_yres - 50,
-               91, 41);
-       ui->pip->setGeometry(status.display_xres/2 + 10,
-               status.display_yres - 50,
-               91, 41);
-       ui->exit->setGeometry(status.display_xres/2 + 120,
-               status.display_yres - 50,
-               91, 41);
-
-       if(status.num_cams == 1) {
-               /* Reconfigure GUI to reflect single camera mode */
-               ui->pip->setHidden(true);
-               ui->pip->setDisabled(true);
-               ui->switch_2->setHidden(true);
-               ui->switch_2->setDisabled(true);
-               ui->frame_pip->setHidden(true);
-               ui->capture->setGeometry(status.display_xres/2 - 100,
-                       status.display_yres - 50,
-                       91, 41);
-               ui->exit->setGeometry(status.display_xres/2 + 10,
-                       status.display_yres - 50,
-                       91, 41);
-       }
-
-       /* Start the camera loopback thread */
-       loopback->start();
-}
-
-MainWindow::~MainWindow()
-{
-       delete ui;
-}
-
-void MainWindow::on_capture_clicked()
-{
-}
-
-void MainWindow::on_switch_2_clicked()
-{
-       /* While changing the drm display properties, make sure loopback thread */
-       /* isn't running thereby accessing drm properties  simultaneously, and  */ 
-       /* hence can cause system crash                                         */
-       drm_resource.lock();
-
-       if (status.num_cams==2){
-               //switch the main camera by toggleing the main_cam value.
-               status.main_cam = !status.main_cam;
-               set_plane_properties();
-       }
-
-       drm_resource.unlock();
-}
-
-void MainWindow::on_pip_clicked()
-{
-       /* While changing the drm display properties, make sure loopback thread */
-       /* isn't running thereby accessing drm properties  simultaneously, and  */ 
-       /* hence can cause system crash                                         */
-       drm_resource.lock();
-
-       if (status.pip==true) {
-               status.pip=false;
-               drm_disable_pip();
-               ui->frame_pip->setHidden(true);
-       }
-       else {
-               drm_enable_pip();
-               ui->frame_pip->setHidden(false);
-               status.pip=true;
-       }
-
-       drm_resource.unlock();
-}
-
-void MainWindow::on_exit_clicked()
-{
-       status.exit=true;
-       loopback->wait(1000);
-       this->close();
-}
-
-void MyThread::run() {
-
-       while(status.exit == false) {
-               drm_resource.lock();
-               process_frame();
-               drm_resource.unlock();  
-               msleep(1);
-       }
-       end_streaming();
-       exit_devices();
-}
-
-
-#include "mainwindow.moc"
diff --git a/mainwindow.h b/mainwindow.h
deleted file mode 100644 (file)
index 13acda1..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include <QApplication>
-#include <QMainWindow>
-
-namespace Ui {
-    class MainWindow;
-}
-
-class MainWindow : public QMainWindow
-{
-    Q_OBJECT
-    
-public:
-    explicit MainWindow(QWidget *parent = 0, QApplication *a = NULL);
-    ~MainWindow();
-    
-private slots:
-    void on_capture_clicked();
-
-    void on_switch_2_clicked();
-
-    void on_pip_clicked();
-
-    void on_exit_clicked();
-
-private:
-    QPlatformNativeInterface *platInf;
-    Ui::MainWindow *ui;
-
-};
-
-#endif // MAINWINDOW_H
diff --git a/mainwindow.ui b/mainwindow.ui
deleted file mode 100644 (file)
index c66cba3..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>800</width>
-    <height>480</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>Dual Camera</string>
-  </property>
-  <widget class="QWidget" name="centralWidget">
-   <widget class="QPushButton" name="capture">
-    <property name="geometry">
-     <rect>
-      <x>190</x>
-      <y>430</y>
-      <width>91</width>
-      <height>41</height>
-     </rect>
-    </property>
-    <property name="palette">
-     <palette>
-      <active>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </active>
-      <inactive>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </inactive>
-      <disabled>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </disabled>
-     </palette>
-    </property>
-    <property name="font">
-     <font>
-      <family>Ubuntu</family>
-      <pointsize>16</pointsize>
-      <weight>50</weight>
-      <italic>false</italic>
-      <bold>false</bold>
-     </font>
-    </property>
-    <property name="styleSheet">
-     <string notr="true">color: rgb(0, 0, 1);</string>
-    </property>
-    <property name="text">
-     <string>Capture</string>
-    </property>
-   </widget>
-   <widget class="QPushButton" name="switch_2">
-    <property name="geometry">
-     <rect>
-      <x>300</x>
-      <y>430</y>
-      <width>91</width>
-      <height>41</height>
-     </rect>
-    </property>
-    <property name="palette">
-     <palette>
-      <active>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </active>
-      <inactive>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </inactive>
-      <disabled>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </disabled>
-     </palette>
-    </property>
-    <property name="font">
-     <font>
-      <family>Ubuntu</family>
-      <pointsize>16</pointsize>
-     </font>
-    </property>
-    <property name="styleSheet">
-     <string notr="true">color: rgb(0, 0, 1);</string>
-    </property>
-    <property name="text">
-     <string>Switch</string>
-    </property>
-   </widget>
-   <widget class="QPushButton" name="pip">
-    <property name="geometry">
-     <rect>
-      <x>410</x>
-      <y>430</y>
-      <width>91</width>
-      <height>41</height>
-     </rect>
-    </property>
-    <property name="palette">
-     <palette>
-      <active>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </active>
-      <inactive>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </inactive>
-      <disabled>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </disabled>
-     </palette>
-    </property>
-    <property name="font">
-     <font>
-      <family>Ubuntu</family>
-      <pointsize>16</pointsize>
-     </font>
-    </property>
-    <property name="styleSheet">
-     <string notr="true">color: rgb(0, 0, 1);</string>
-    </property>
-    <property name="text">
-     <string>PiP</string>
-    </property>
-   </widget>
-   <widget class="QPushButton" name="exit">
-    <property name="geometry">
-     <rect>
-      <x>520</x>
-      <y>430</y>
-      <width>91</width>
-      <height>41</height>
-     </rect>
-    </property>
-    <property name="palette">
-     <palette>
-      <active>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </active>
-      <inactive>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </inactive>
-      <disabled>
-       <colorrole role="WindowText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="Text">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-       <colorrole role="ButtonText">
-        <brush brushstyle="SolidPattern">
-         <color alpha="255">
-          <red>0</red>
-          <green>0</green>
-          <blue>1</blue>
-         </color>
-        </brush>
-       </colorrole>
-      </disabled>
-     </palette>
-    </property>
-    <property name="font">
-     <font>
-      <family>Ubuntu</family>
-      <pointsize>16</pointsize>
-     </font>
-    </property>
-    <property name="styleSheet">
-     <string notr="true">color: rgb(0, 0, 1);</string>
-    </property>
-    <property name="text">
-     <string>Exit</string>
-    </property>
-   </widget>
-   <widget class="QFrame" name="frame">
-    <property name="geometry">
-     <rect>
-      <x>0</x>
-      <y>0</y>
-      <width>800</width>
-      <height>480</height>
-     </rect>
-    </property>
-    <property name="styleSheet">
-     <string notr="true">color: rgb(212, 208, 200);</string>
-    </property>
-    <property name="frameShape">
-     <enum>QFrame::Panel</enum>
-    </property>
-    <property name="frameShadow">
-     <enum>QFrame::Plain</enum>
-    </property>
-    <property name="lineWidth">
-     <number>3</number>
-    </property>
-   </widget>
-   <widget class="QFrame" name="frame_pip">
-    <property name="geometry">
-     <rect>
-      <x>0</x>
-      <y>0</y>
-      <width>400</width>
-      <height>240</height>
-     </rect>
-    </property>
-    <property name="styleSheet">
-     <string notr="true">color: rgb(212, 208, 200);</string>
-    </property>
-    <property name="frameShape">
-     <enum>QFrame::Panel</enum>
-    </property>
-    <property name="frameShadow">
-     <enum>QFrame::Plain</enum>
-    </property>
-    <property name="lineWidth">
-     <number>3</number>
-    </property>
-   </widget>
-   <zorder>frame</zorder>
-   <zorder>capture</zorder>
-   <zorder>exit</zorder>
-   <zorder>switch_2</zorder>
-   <zorder>pip</zorder>
-   <zorder>frame_pip</zorder>
-  </widget>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <resources/>
- <connections/>
-</ui>
diff --git a/maroon.qml b/maroon.qml
new file mode 100755 (executable)
index 0000000..2582fd7
--- /dev/null
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Particles 2.0
+import "content"
+import "content/logic.js" as Logic
+
+Item {
+    id: root
+    width: 320
+    height: 480
+    property var gameState
+    property bool passedSplash: false
+
+    Image {
+        source:"content/gfx/background.png"
+        anchors.bottom: view.bottom
+
+        ParticleSystem {
+            id: particles
+            anchors.fill: parent
+
+            ImageParticle {
+                id: bubble
+                anchors.fill: parent
+                source: "content/gfx/catch.png"
+                opacity: 0.25
+            }
+
+            Wander {
+                xVariance: 25;
+                pace: 25;
+            }
+
+            Emitter {
+                width: parent.width
+                height: 150
+                anchors.bottom: parent.bottom
+                anchors.bottomMargin: 3
+                startTime: 15000
+
+                emitRate: 2
+                lifeSpan: 15000
+
+                acceleration: PointDirection{ y: -6; xVariation: 2; yVariation: 2 }
+
+                size: 24
+                sizeVariation: 16
+            }
+        }
+    }
+
+    Column {
+        id: view
+        y: -(height - 480)
+        width: 320
+
+        GameOverScreen { gameCanvas: canvas }
+
+        Item {
+            id: canvasArea
+            width: 320
+            height: 480
+
+            Row {
+                height: childrenRect.height
+                Image {
+                    id: wave
+                    y: 30
+                    source:"content/gfx/wave.png"
+                }
+                Image {
+                    y: 30
+                    source:"content/gfx/wave.png"
+                }
+                NumberAnimation on x { from: 0; to: -(wave.width); duration: 16000; loops: Animation.Infinite }
+                SequentialAnimation on y {
+                    loops: Animation.Infinite
+                    NumberAnimation { from: y - 2; to: y + 2; duration: 1600; easing.type: Easing.InOutQuad }
+                    NumberAnimation { from: y + 2; to: y - 2; duration: 1600; easing.type: Easing.InOutQuad }
+                }
+            }
+
+            Row {
+                opacity: 0.5
+                Image {
+                    id: wave2
+                    y: 25
+                    source: "content/gfx/wave.png"
+                }
+                Image {
+                    y: 25
+                    source: "content/gfx/wave.png"
+                }
+                NumberAnimation on x { from: -(wave2.width); to: 0; duration: 32000; loops: Animation.Infinite }
+                SequentialAnimation on y {
+                    loops: Animation.Infinite
+                    NumberAnimation { from: y + 2; to: y - 2; duration: 1600; easing.type: Easing.InOutQuad }
+                    NumberAnimation { from: y - 2; to: y + 2; duration: 1600; easing.type: Easing.InOutQuad }
+                }
+            }
+
+            Image {
+                source: "content/gfx/sunlight.png"
+                opacity: 0.02
+                y: 0
+                anchors.horizontalCenter: parent.horizontalCenter
+                transformOrigin: Item.Top
+                SequentialAnimation on rotation {
+                    loops: Animation.Infinite
+                    NumberAnimation { from: -10; to: 10; duration: 8000; easing.type: Easing.InOutSine }
+                    NumberAnimation { from: 10; to: -10; duration: 8000; easing.type: Easing.InOutSine }
+                }
+            }
+
+            Image {
+                source: "content/gfx/sunlight.png"
+                opacity: 0.04
+                y: 20
+                anchors.horizontalCenter: parent.horizontalCenter
+                transformOrigin: Item.Top
+                SequentialAnimation on rotation {
+                    loops: Animation.Infinite
+                    NumberAnimation { from: 10; to: -10; duration: 8000; easing.type: Easing.InOutSine }
+                    NumberAnimation { from: -10; to: 10; duration: 8000; easing.type: Easing.InOutSine }
+                }
+            }
+
+            Image {
+                source: "content/gfx/grid.png"
+                opacity: 0.5
+            }
+
+            GameCanvas {
+                id: canvas
+                anchors.bottom: parent.bottom
+                anchors.bottomMargin: 20
+                x: 32
+                focus: true
+            }
+
+            InfoBar { anchors.bottom: canvas.top; anchors.bottomMargin: 6; width: parent.width }
+
+            //3..2..1..go
+            Timer {
+                id: countdownTimer
+                interval: 1000
+                running: root.countdown < 5
+                repeat: true
+                onTriggered: root.countdown++
+            }
+            Repeater {
+                model: ["content/gfx/text-blank.png", "content/gfx/text-3.png", "content/gfx/text-2.png", "content/gfx/text-1.png", "content/gfx/text-go.png"]
+                delegate: Image {
+                    visible: root.countdown <= index
+                    opacity: root.countdown == index ? 0.5 : 0.1
+                    scale: root.countdown >= index ? 1.0 : 0.0
+                    source: modelData
+                    Behavior on opacity { NumberAnimation {} }
+                    Behavior on scale { NumberAnimation {} }
+                }
+            }
+        }
+
+        NewGameScreen {
+            onStartButtonClicked: root.passedSplash = true
+        }
+    }
+
+    property int countdown: 10
+    Timer {
+        id: gameStarter
+        interval: 4000
+        running: false
+        repeat: false
+        onTriggered: Logic.startGame(canvas);
+    }
+
+    states: [
+        State {
+            name: "gameOn"; when: gameState.gameOver == false && passedSplash
+            PropertyChanges { target: view; y: -(height - 960) }
+            StateChangeScript { script: root.countdown = 0; }
+            PropertyChanges { target: gameStarter; running: true }
+        },
+        State {
+            name: "gameOver"; when: gameState.gameOver == true
+            PropertyChanges { target: view; y: 0 }
+        }
+    ]
+
+    transitions: Transition {
+        NumberAnimation { properties: "x,y"; duration: 1200; easing.type: Easing.OutQuad }
+    }
+
+    Component.onCompleted: gameState = Logic.newGameState(canvas);
+}
diff --git a/qpa_ctl.cpp b/qpa_ctl.cpp
new file mode 100755 (executable)
index 0000000..b747e94
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#include <qpa/qplatformnativeinterface.h>
+#include "qpa_ctl.h"
+#include "error.h"
+
+/* eglfs_kms QT QPA provides API to user space so that it can submit the 
+* video planes to be scaled, color converted and overlayed on top of graphics 
+* planes and displayed to the panel/monitor. All eglfs_kms APIs function pointers 
+* are stored in QpaCtlObj once and then later used by DispObJ to intercat with QT QPA
+*/
+
+QpaCtlObj::QpaCtlObj(QGuiApplication *a)
+{
+    QPlatformNativeInterface *platInf = a->platformNativeInterface();
+
+    m_export_buffer =  (fnptr_export_buf)platInf->nativeResourceForIntegration("export_buffer");
+    m_distroy_buffer =  (fnptr_distroy_buf)platInf->nativeResourceForIntegration("distroy_buffer");
+    m_create_plane  = \
+        (fnptr_create_pln)platInf->nativeResourceForIntegration("create_plane");
+    m_distroy_plane  = \
+        (fnptr_distroy_pln)platInf->nativeResourceForIntegration("distroy_plane");
+    m_set_plane_properties = \
+        (fnptr_set_pln_prop)platInf->nativeResourceForIntegration("set_plane_properties");
+    m_get_plane_property = \
+        (fnptr_get_pln_prop)platInf->nativeResourceForIntegration("get_plane_property");
+    m_queue_buffer =  (fnptr_queue_pln)platInf->nativeResourceForIntegration("queue_plane");
+    m_start_disp_plane =  (fnptr_start_disp_pln)platInf->nativeResourceForIntegration("start_disp_plane");
+    m_set_user_call_back =  (fnptr_set_user_callbk)platInf->nativeResourceForIntegration("user_call_back_handle");
+}
+
diff --git a/qpa_ctl.h b/qpa_ctl.h
new file mode 100755 (executable)
index 0000000..a2827d4
--- /dev/null
+++ b/qpa_ctl.h
@@ -0,0 +1,73 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef QPA_CTL_H
+#define QPA_CTL_H
+
+#include <QGuiApplication>
+
+typedef int (*fnptr_export_buf)(void *screen, uint32_t width, 
+                                uint32_t height, uint32_t pixel_format,        uint32_t *strides, 
+                                uint32_t *offsets, uint32_t buf_fd, uint32_t *buf_id);
+typedef int (*fnptr_distroy_buf)(void *screen, uint32_t buf_id);
+
+typedef        int (*fnptr_create_pln)(void *screen);
+typedef        int (*fnptr_distroy_pln)(void *screen, uint32_t idx);
+
+typedef        int (*fnptr_set_pln_prop)(void *screen, uint8_t planeType,
+                                  uint32_t idx, uint8_t num_prop, const char **prop_name, uint32_t *prop_val);
+typedef        int (*fnptr_get_pln_prop)(void *screen, uint8_t planeType,
+                                  uint32_t idx, const char *prop_name);
+
+typedef int (*fnptr_queue_pln)(void *screen, uint32_t idx, uint32_t fb_id);
+typedef int (*fnptr_start_disp_pln)(void *screen);
+typedef        int (*fnptr_dequeue_pln)(void *screen, int block_time);
+typedef        int (*fnptr_set_user_callbk)(void *screen, void (*func)(void *), void *data);
+
+class QpaCtlObj{
+public:
+    QpaCtlObj(QGuiApplication *a);
+    fnptr_export_buf    m_export_buffer;
+    fnptr_distroy_buf   m_distroy_buffer;
+    fnptr_create_pln    m_create_plane;
+    fnptr_distroy_pln   m_distroy_plane;
+    fnptr_set_pln_prop  m_set_plane_properties;
+    fnptr_get_pln_prop  m_get_plane_property;
+    fnptr_queue_pln            m_queue_buffer;
+    fnptr_dequeue_pln   m_dequeue_buffer;
+    fnptr_start_disp_pln m_start_disp_plane;
+    fnptr_set_user_callbk m_set_user_call_back;
+};
+
+#endif // QPA_CTL_H
diff --git a/v4l2_obj.cpp b/v4l2_obj.cpp
new file mode 100755 (executable)
index 0000000..b2ae9fb
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+/* This file defines the function to program V4L2 device */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <iostream>
+#include <sys/ioctl.h>
+#include "v4l2_obj.h"
+#include "error.h"
+
+#define NBUF (3)
+#define CAP_WIDTH 800
+#define CAP_HEIGHT 600
+
+/*
+* Initialize the app resources with default parameters
+*/
+void V4l2Obj::default_parameters(void) {
+    /* Main camera */
+    m_num_buffers = NBUF;
+    strcpy(m_dev_name,"/dev/video1");
+    m_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+    m_width = CAP_WIDTH;
+    m_height = CAP_HEIGHT;
+    m_v4l2buf = NULL;
+
+    return;
+}
+
+void V4l2Obj::device_init(int pix_fmt){
+    struct v4l2_capability capability;
+    struct v4l2_streamparm streamparam;
+    int ret;
+
+    /* Open the capture device */
+    m_fd = open(m_dev_name, O_RDWR);
+
+    if (m_fd <= 0) {
+        ERROR("Cannot open %s device\n\n", m_dev_name);
+        return;
+    }
+
+    MSG("\n%s: Opened Channel\n", m_dev_name);
+
+    /* Check if the device is capable of streaming */
+    if (ioctl(m_fd, VIDIOC_QUERYCAP, &capability) < 0) {
+        perror("VIDIOC_QUERYCAP");
+        goto ERR;
+    }
+
+    if (capability.capabilities & V4L2_CAP_STREAMING)
+        MSG("%s: Capable of streaming\n", m_dev_name);
+    else {
+        ERROR("%s: Not capable of streaming\n", m_dev_name);
+        goto ERR;
+    }
+
+    streamparam.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    if (ioctl(m_fd, VIDIOC_G_PARM, &streamparam) < 0){
+        ERROR("VIDIOC_G_PARM");
+        goto ERR;
+    }
+
+    m_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    ret = ioctl(m_fd, VIDIOC_G_FMT, &m_fmt);
+    if (ret < 0) {
+        ERROR("VIDIOC_G_FMT failed: %s (%d)", strerror(errno), ret);
+        goto ERR;
+    }
+
+    m_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    m_fmt.fmt.pix.width = m_width;
+    m_fmt.fmt.pix.height = m_height;
+    m_fmt.fmt.pix.pixelformat = pix_fmt;
+
+    ret = ioctl(m_fd, VIDIOC_S_FMT, &m_fmt);
+    if (ret < 0) {
+        ERROR("VIDIOC_S_FMT");
+        goto ERR;
+    }
+
+    MSG("%s: Init done successfully\n", m_dev_name);
+    return;
+ERR:
+    close(m_fd);
+    return;
+}
+
+V4l2Obj::V4l2Obj(){
+    default_parameters();
+    device_init(V4L2_PIX_FMT_YUYV);
+}
+
+V4l2Obj::V4l2Obj(const char * dev_name, int w, int h, int pix_fmt, int num_buf){
+    default_parameters();
+
+    strcpy(m_dev_name,dev_name);
+    m_width = w;
+    m_height = h;
+    m_num_buffers = num_buf;
+    //m_fmt.fmt.pix.pixelformat = pix_fmt;
+
+    device_init(pix_fmt);
+}
+
+V4l2Obj::~V4l2Obj(){
+    free(m_v4l2buf);
+    close(m_fd);
+
+    return;
+}
+
+/* In this example appliaction, user space allocates the buffers and 
+ * provides the buffer fd to be exported to the V4L2 driver 
+*/
+int V4l2Obj::request_buf(int *fd){
+    struct v4l2_requestbuffers reqbuf;
+    uint32_t i;
+    int ret;
+
+    if (m_v4l2buf) {
+        // maybe eventually need to support this?
+        ERROR("already reqbuf'd");
+        return -1;
+    }
+
+    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    reqbuf.memory = V4L2_MEMORY_DMABUF;
+    reqbuf.count = m_num_buffers;
+
+    ret = ioctl(m_fd, VIDIOC_REQBUFS, &reqbuf);
+    if (ret < 0) {
+        ERROR("VIDIOC_REQBUFS failed: %s (%d)", strerror(errno), ret);
+        return ret;
+    }
+
+    if ((reqbuf.count != m_num_buffers) ||
+        (reqbuf.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+        (reqbuf.memory != V4L2_MEMORY_DMABUF)) {
+            ERROR("unsupported..");
+            return -1;
+    }
+
+    m_num_buffers = reqbuf.count;
+    m_v4l2buf = (struct v4l2_buffer *) calloc(m_num_buffers, \
+        sizeof(struct v4l2_buffer));
+    if (!m_v4l2buf) {
+        ERROR("allocation failed");
+        return -1;
+    }
+
+    for (i = 0; i < m_num_buffers; i++) {
+        m_v4l2buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        m_v4l2buf[i].memory = V4L2_MEMORY_DMABUF;
+        m_v4l2buf[i].index = i;
+
+        ret = ioctl(m_fd, VIDIOC_QUERYBUF, &m_v4l2buf[i]);
+        m_v4l2buf[i].m.fd = fd[i];
+
+        if (ret) {
+            ERROR("VIDIOC_QUERYBUF failed: %s (%d)", strerror(errno), ret);
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+/*
+* Queue V4L2 buffer
+*/
+int V4l2Obj::queue_buf(int fd){
+    struct v4l2_buffer *v4l2buf = NULL;
+    int  ret;
+    unsigned char i;
+
+
+    for (i = 0; i < m_num_buffers; i++) {
+        if (m_v4l2buf[i].m.fd == fd) {
+            v4l2buf = &m_v4l2buf[i];
+        }
+    }
+
+    if (!v4l2buf) {
+        ERROR("invalid buffer");
+        return -1;
+    }
+    ret = ioctl(m_fd, VIDIOC_QBUF, v4l2buf);
+    if (ret) {
+        ERROR("VIDIOC_QBUF failed: %s (%d)", strerror(errno), ret);
+    }
+
+    return ret;
+}
+
+/*
+* DeQueue V4L2 buffer
+*/
+int V4l2Obj::dequeue_buf(){
+    struct v4l2_buffer v4l2buf;
+    int ret;
+
+    v4l2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    v4l2buf.memory = V4L2_MEMORY_DMABUF;
+    ret = ioctl(m_fd, VIDIOC_DQBUF, &v4l2buf);
+    if (ret) {
+        ERROR("VIDIOC_DQBUF failed: %s (%d)\n", strerror(errno), ret);
+        return -1;
+    }
+
+    m_v4l2buf[v4l2buf.index].timestamp = v4l2buf.timestamp;
+
+    return v4l2buf.index;
+}
+
+/*
+* Enable streaming for V4L2 capture device
+*/
+int V4l2Obj::stream_on(){
+    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    int ret = 0;
+
+    ret = ioctl(m_fd, VIDIOC_STREAMON, &type);
+
+    if (ret) {
+        ERROR("VIDIOC_STREAMON failed: %s (%d)", strerror(errno), ret);
+    }
+
+    return ret;
+}
+
+/*
+* Disable streaming for V4L2 capture device
+*/
+int V4l2Obj::stream_off(){
+    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    int ret = -1;
+
+    if (m_fd <= 0) {
+        return ret;
+    }
+
+    ret = ioctl(m_fd, VIDIOC_STREAMOFF, &type);
+
+    if (ret) {
+        ERROR("VIDIOC_STREAMOFF failed: %s (%d)", strerror(errno), ret);
+    }
+
+    return ret;
+}
diff --git a/v4l2_obj.h b/v4l2_obj.h
new file mode 100755 (executable)
index 0000000..832bb33
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef V4L2_OBJ_H
+#define V4L2_OBJ_H
+
+#include <linux/videodev2.h>
+/*
+* V4L2 Object class declaration
+*/
+class V4l2Obj {
+public: 
+       V4l2Obj();
+       V4l2Obj(const char * dev_name, int w, int h, int pix_fmt, int num_buf);
+   ~V4l2Obj();
+    
+   int request_buf(int *fd);
+   int queue_buf(int fd);
+   int dequeue_buf();
+   int stream_off();
+   int stream_on();
+
+private:
+       int m_fd;
+       uint32_t m_num_buffers;
+       uint32_t m_width;
+       uint32_t m_height;
+       char m_dev_name[256];
+       struct v4l2_buffer *m_v4l2buf;
+       struct v4l2_format m_fmt;
+       void default_parameters();
+       void device_init(int pix_fmt);
+};
+
+#endif // V4L2_OBJ_H
diff --git a/video_graphics_test.cpp b/video_graphics_test.cpp
new file mode 100755 (executable)
index 0000000..248a7d5
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#include <QGuiApplication>
+#include <QScreen>
+#include <QThread>
+#include <QQueue>
+#include <unistd.h>
+#include "cmem_buf.h"
+#include "v4l2_obj.h"
+#include "qpa_ctl.h"
+#include "disp_obj.h"
+#include "error.h"
+#include "video_graphics_test.h"
+#include "gc320.h"
+
+#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | \
+    ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | \
+    ((uint32_t)(uint8_t)(d) << 24 ))
+#define FOURCC_STR(str)    FOURCC(str[0], str[1], str[2], str[3])
+
+#define DISP_QUEUE_DEPTH 4
+#define NUM_CAP_BUFS      (DISP_QUEUE_DEPTH+3)
+#define NUM_GC320_BUFS    (DISP_QUEUE_DEPTH+1)
+#define CAP_W 640
+#define CAP_H 480
+#define DEQUEUE_WAIT_TIME 100 //worst case wait for 30 ms before flagging error
+
+uint32_t gc320_buf_idx[NUM_GC320_BUFS];
+
+void run_video_graphics_test(BufObj *bo_cap, BufObj *bo_gc320, V4l2Obj *cap,
+                                                        Gc320Obj *gc320_proc, DispObj *disp1, DispObj *disp2){
+    bool dual_display = (g_qt_app->screens().count() > 1) ? true : false;
+    int gc320_buf_idx = 0;
+    int frm_cnt = 0, disp_qdepth = 0;
+    struct timeval start, now;
+       QQueue<uint32_t> cap_buf_idx;
+    gettimeofday(&start, NULL);
+    
+    while(1){
+
+        //Get the capture video
+        int cap_buf_index = cap->dequeue_buf();
+
+        //Call GC320 for 90 degree rotation on captured video
+        gc320_proc->rotation_90deg(cap_buf_index, gc320_buf_idx);
+
+        //Queue the GC320 processed video to scale, overlay and alpha blend with graphics and display on DISPLAY1
+        //There can be multiple (on AM57x, upto 3 planes) video planes that can be submitted to same display
+        disp1->queue_buf(0, bo_gc320->m_fb_id[gc320_buf_idx]);
+
+        //Queue the captured video to scale, overlay and alpha blend with graphics and display on DISPLAY2
+        if(dual_display)
+            disp2->queue_buf(0, bo_cap->m_fb_id[cap_buf_index]);
+
+        disp_qdepth++;
+
+        cap_buf_idx.enqueue(cap_buf_index);
+
+        /* Start displaying once the QT QPA display queue for user plane is full. Queue depth depends 
+        upon the difference between capture and display processing rate. Display LCD panel/HDMI monitor
+        on IDK and GP EVM can handle 60 fps. The camera on IDK can only capture 640x480 at 43 fps */
+        if(disp_qdepth == DISP_QUEUE_DEPTH){
+            disp1->start_disp();
+
+            if(dual_display)
+                disp2->start_disp();
+        }
+
+        if(disp_qdepth >= DISP_QUEUE_DEPTH){
+
+            //Dequeue video plane buffer submitted on DISPLAY1
+            disp1->dequeue_bufs(DEQUEUE_WAIT_TIME);
+
+            //Dequeue video plane buffer submitted on DISPLAY2
+            /* Since there are two seperate monitors running asynchronously and have
+            there own display rate, it's not good idea to wait for the display completion
+            for second monitor on same thread. Ideally there should be two independent thread 
+            driving two monitors. For simplification of the app, we are doing in one single thread.
+            Not waiting here for the display completion of second screeen is not having any impact 
+            as GC320 processing and submission of it to display queue is happening sequentially.
+            */
+            //if(dual_display)
+            //disp2->dequeue_bufs(DEQUEUE_WAIT_TIME);
+
+            //Queue the released buffer to capture pool
+            if (cap->queue_buf(bo_cap->m_fd[cap_buf_idx.dequeue()]) < 0) {
+                exit(-1);
+            }
+        }
+
+        gc320_buf_idx = (gc320_buf_idx+1) % NUM_GC320_BUFS;
+
+        if(frm_cnt++ == 30){
+            frm_cnt = 0;
+            gettimeofday(&now, NULL);
+            /* Performance will be govern by the slowest engine in the pipeline. In this 
+            example, Ov2659 sensor streams VGA capture at 43 fps on IDK EVM and is the slowest in the pipeline.
+            On GP EVM, MT9T111 will capture VGA @ 30 fps. 
+            */
+            MSG("time taken to process 30 frames in ms = %d\n", 
+                (int) (((now.tv_sec - start.tv_sec)*1000) + (now.tv_usec - start.tv_usec)/1000));
+            start = now;
+        }
+    }
+}
+void VideoGraphicsThread::run(){
+
+    uint32_t cap_w = CAP_W;
+    uint32_t cap_h = CAP_H;
+
+    /* Since in this example GC320 is rotating the capture video input to 90 degree,
+          make sure the GC320 output buffer width is larger than capture buffer height */
+       uint32_t gc320_out_w = (cap_w > cap_h) ? cap_w : cap_h; // 
+    uint32_t gc320_out_h = gc320_out_w;
+
+    bool dual_display = (g_qt_app->screens().count() > 1) ? true : false;
+
+    //Create buffer objects for camera capture
+    BufObj bo_cap(cap_w, cap_h, 2, FOURCC_STR("YUYV"), 1, NUM_CAP_BUFS);
+
+    //Create VIP capture object
+    //Open camera node on VIP1 and configure it to capture video of resoultion cap_w X cap_h in YUYv format
+    V4l2Obj vip_cap("/dev/video1", cap_w, cap_h, FOURCC_STR("YUYV"), NUM_CAP_BUFS);
+
+    // Request, configure the V4l2 buffers
+    //Export the application allocated buffers (from CMEM driver) to VIP capture drivers 
+    if (vip_cap.request_buf(bo_cap.m_fd) < 0) {
+        ERROR("V4l2 capture buffers already allocated\n");
+        exit(-1);
+    }
+
+    /*Create buffer objects for GC320 output
+       * Vivante needs address to be 0x80 bytes aligned
+       * Vivante HAL needs 16 pixel alignment in width and 4 pixel alignment in
+    * height.
+    */
+    BufObj bo_gc320_out(gc320_out_w, gc320_out_h, 2, FOURCC_STR("YUYV"), 0x80, NUM_GC320_BUFS);
+
+    //Create GC320 object
+    //Initialize GC320 core, and it's input and output surfaces
+    Gc320Obj gc320_proc(NUM_CAP_BUFS, NUM_GC320_BUFS, &bo_cap, &bo_gc320_out);
+
+    //Create QT QPA object to get handles of various APIs from QT QPA to configure DSS hardware planes for video scaling and overlays
+    QpaCtlObj qpa_ctl(g_qt_app);
+
+    //Create Display1 Object
+    //Pass on handles from QT QPA, create video overlay planes for DISPLAY1 and set the video plane display resolution  
+    DispObj disp1(&qpa_ctl,  (void *)g_qt_app->screens().at(0), 0, 0, 
+        g_qt_app->screens().at(0)->geometry().width(), g_qt_app->screens().at(0)->geometry().height(), 1);
+
+    //Create Display2 Object
+    //Pass on handles from QT QPA, create video overlay planes for DISPLAY2 and set the video plane display resolution 
+    uint32_t disp_w = 0;
+    uint32_t disp_h = 0;
+    void *screen = NULL;
+    if(dual_display){
+        screen = (void *)g_qt_app->screens().at(1);
+        disp_w = g_qt_app->screens().at(1)->geometry().width();
+        disp_h = g_qt_app->screens().at(1)->geometry().height();
+    }
+       
+       DispObj disp2(&qpa_ctl, screen, 0, 0, disp_w, disp_h, 1);
+
+       uint32_t offset = 0;
+    for (uint32_t i = 0; i < NUM_GC320_BUFS; i++) {
+               /* Export the video overlay buffers to DISPLAY1
+               GC320 processed (90 degree rotated) video will be displayed on DISPLAY1
+               Since the video is 90 degree rotated to original content, buffer width and height are swapped
+               */
+        disp1.export_buf2_qpa(cap_h, cap_w, FOURCC_STR("YUYV"), &bo_gc320_out.m_stride, &offset,  bo_gc320_out.m_fd[i], 
+            &bo_gc320_out.m_fb_id[i]);
+    }
+
+    for (uint32_t i = 0; i < NUM_CAP_BUFS; i++) {
+        //Queue capture buffers 
+        vip_cap.queue_buf(bo_cap.m_fd[i]);
+
+        //Export the video overlay buffers to DISPLAY2
+        //Camera captured buffers will be displayed on DISPLAY2
+        if(dual_display)
+            disp2.export_buf2_qpa(cap_w, cap_h, FOURCC_STR("YUYV"), &bo_cap.m_stride, &offset,  bo_cap.m_fd[i], 
+            &bo_cap.m_fb_id[i]);
+    }
+
+    //Set the DSS hardware video plane properties for Display1
+    //Since we are rotating the capture buffer by 90 degree and displaying it, the width and height are swapped
+    disp1.set_properties(cap_h, cap_w, bo_gc320_out.m_fb_id[0], 0);
+
+    //Set the DSS hardware video plane properties for Display2
+    if(dual_display)
+        disp2.set_properties(cap_w, cap_h, bo_cap.m_fb_id[0], 0);
+
+    //Start camera streaming
+    if (vip_cap.stream_on() < 0) exit(-1);
+
+    run_video_graphics_test(&bo_cap, &bo_gc320_out, &vip_cap, &gc320_proc, &disp1, &disp2);
+}
diff --git a/video_graphics_test.h b/video_graphics_test.h
new file mode 100755 (executable)
index 0000000..ef9ef48
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+* 
+* 
+*  Redistribution and use in source and binary forms, with or without 
+*  modification, are permitted provided that the following conditions 
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright 
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the 
+*    documentation and/or other materials provided with the   
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef VIDEO_GRAPHICS_TEST_H
+#define VIDEO_GRAPHICS_TEST_H
+#include <QThread>
+#include <QGuiApplication>
+
+class VideoGraphicsThread : public QThread
+{
+protected:
+    void run();
+};
+
+extern QGuiApplication *g_qt_app;
+
+#endif // VIDEO_GRAPHICS_TEST_H
index 9a5584f3b119c6db64fb010ff6ebf523b33652c6..0344e62e1d33e51b7d629c942dda05c311c5f93a 100644 (file)
@@ -1,19 +1,17 @@
-#-------------------------------------------------
-#
-# Project created by QtCreator 2014-01-15T08:40:35
-#
-#-------------------------------------------------
-QT       += core gui widgets platformsupport-private
-
-lessThan(QT_MAJOR_VERSION, 4): QT += threads
-
-TARGET = video_graphics_test
 TEMPLATE = app
-LIBS += -ldrm_omap -ldrm 
+
+QT += quick core platformsupport-private
+LIBS += -lticmem 
+LIBS += -lGAL 
+LIBS += -lstdc++
 
 INCLUDEPATH += $(SDK_PATH_TARGET)/usr/include/libdrm \
-              $(SDK_PATH_TARGET)/usr/include/omap 
+              $(SDK_PATH_TARGET)/usr/include/omap \
+              $(SDK_PATH_TARGET)/usr/include/HAL2D
+              
+SOURCES = main.cpp cmem_buf.cpp v4l2_obj.cpp qpa_ctl.cpp disp_obj.cpp video_graphics_test.cpp gc320.cpp
+HEADERS  +=  cmem_buf.h v4l2_obj.h qpa_ctl.h disp_obj.h video_graphics_test.h gc320.h
 
-SOURCES += main.cpp mainwindow.cpp loopback.c
-HEADERS  += mainwindow.h loopback.h
-FORMS    += mainwindow.ui
+RESOURCES = video_graphics_test.qrc
+OTHER_FILES = screen.qml
+INSTALLS += target
diff --git a/video_graphics_test.qrc b/video_graphics_test.qrc
new file mode 100644 (file)
index 0000000..9820455
--- /dev/null
@@ -0,0 +1,82 @@
+<RCC>
+    <qresource prefix="/">
+      <file>clocks.qml</file>
+      <file>content/arrow.png</file>
+      <file>content/background.png</file>
+      <file>content/center.png</file>
+      <file>content/clock-night.png</file>
+      <file>content/clock.png</file>
+      <file>content/Clock.qml</file>
+      <file>content/hour.png</file>
+      <file>content/minute.png</file>
+      <file>content/quit.png</file>
+      <file>content/second.png</file>
+      <file>maroon.qml</file>
+      <file>content/BuildButton.qml</file>
+      <file>content/GameCanvas.qml</file>
+      <file>content/GameOverScreen.qml</file>
+      <file>content/InfoBar.qml</file>
+      <file>content/logic.js</file>
+      <file>content/NewGameScreen.qml</file>
+      <file>content/SoundEffect.qml</file>
+      <file>content/audio/bomb-action.wav</file>
+      <file>content/audio/catch-action.wav</file>
+      <file>content/audio/catch.wav</file>
+      <file>content/audio/currency.wav</file>
+      <file>content/audio/factory-action.wav</file>
+      <file>content/audio/melee-action.wav</file>
+      <file>content/audio/projectile-action.wav</file>
+      <file>content/audio/shooter-action.wav</file>
+      <file>content/gfx/background.png</file>
+      <file>content/gfx/bomb-action.png</file>
+      <file>content/gfx/bomb-idle.png</file>
+      <file>content/gfx/bomb.png</file>
+      <file>content/gfx/button-help.png</file>
+      <file>content/gfx/button-play.png</file>
+      <file>content/gfx/catch-action.png</file>
+      <file>content/gfx/catch.png</file>
+      <file>content/gfx/cloud.png</file>
+      <file>content/gfx/currency.png</file>
+      <file>content/gfx/dialog-bomb.png</file>
+      <file>content/gfx/dialog-factory.png</file>
+      <file>content/gfx/dialog-melee.png</file>
+      <file>content/gfx/dialog-pointer.png</file>
+      <file>content/gfx/dialog-shooter.png</file>
+      <file>content/gfx/dialog.png</file>
+      <file>content/gfx/factory-action.png</file>
+      <file>content/gfx/factory-idle.png</file>
+      <file>content/gfx/factory.png</file>
+      <file>content/gfx/grid.png</file>
+      <file>content/gfx/help.png</file>
+      <file>content/gfx/lifes.png</file>
+      <file>content/gfx/logo-bubble.png</file>
+      <file>content/gfx/logo-fish.png</file>
+      <file>content/gfx/logo.png</file>
+      <file>content/gfx/melee-action.png</file>
+      <file>content/gfx/melee-idle.png</file>
+      <file>content/gfx/melee.png</file>
+      <file>content/gfx/mob-idle.png</file>
+      <file>content/gfx/mob.png</file>
+      <file>content/gfx/points.png</file>
+      <file>content/gfx/projectile-action.png</file>
+      <file>content/gfx/projectile.png</file>
+      <file>content/gfx/scores.png</file>
+      <file>content/gfx/shooter-action.png</file>
+      <file>content/gfx/shooter-idle.png</file>
+      <file>content/gfx/shooter.png</file>
+      <file>content/gfx/sunlight.png</file>
+      <file>content/gfx/text-1.png</file>
+      <file>content/gfx/text-2.png</file>
+      <file>content/gfx/text-3.png</file>
+      <file>content/gfx/text-blank.png</file>
+      <file>content/gfx/text-gameover.png</file>
+      <file>content/gfx/text-go.png</file>
+      <file>content/gfx/wave.png</file>
+      <file>content/mobs/MobBase.qml</file>
+      <file>content/towers/Bomb.qml</file>
+      <file>content/towers/Factory.qml</file>
+      <file>content/towers/Melee.qml</file>
+      <file>content/towers/Ranged.qml</file>
+      <file>content/towers/TowerBase.qml</file>
+    </qresource>
+</RCC>