summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/vigs/vigs_backend.h3
-rw-r--r--hw/vigs/vigs_device.c25
-rw-r--r--hw/vigs/vigs_gl_backend.c39
-rw-r--r--hw/vigs/vigs_gl_backend_glx.c13
-rw-r--r--hw/vigs/vigs_onscreen_server.c49
-rw-r--r--hw/vigs/vigs_onscreen_server.h15
-rw-r--r--hw/vigs/vigs_qt5.cpp23
-rw-r--r--hw/vigs/vigs_qt5.h6
-rw-r--r--hw/vigs/vigs_server.c11
-rw-r--r--hw/vigs/vigs_server.h3
-rw-r--r--hw/vigs/vigs_sw_backend.c9
-rw-r--r--tizen/src/display/qt5_supplement.cpp31
-rw-r--r--tizen/src/ui/mainwindow.cpp42
-rw-r--r--tizen/src/ui/mainwindow.h7
-rw-r--r--tizen/src/ui/menu/contextmenu.cpp11
-rw-r--r--tizen/src/ui/menu/contextmenu.h1
16 files changed, 285 insertions, 3 deletions
diff --git a/hw/vigs/vigs_backend.h b/hw/vigs/vigs_backend.h
index c300195f35..bbbd90abfe 100644
--- a/hw/vigs/vigs_backend.h
+++ b/hw/vigs/vigs_backend.h
@@ -54,6 +54,9 @@ struct vigs_backend
bool /*planes_dirty*/,
uint8_t */*display_data*/);
+ bool (*capture)(struct vigs_surface */*surface*/,
+ void */*pixels*/);
+
void (*batch_end)(struct vigs_backend */*backend*/);
bool (*display)(struct vigs_backend */*backend*/,
diff --git a/hw/vigs/vigs_device.c b/hw/vigs/vigs_device.c
index 90bd2af6aa..8e190df32f 100644
--- a/hw/vigs/vigs_device.c
+++ b/hw/vigs/vigs_device.c
@@ -291,6 +291,23 @@ static void vigs_io_write(void *opaque, hwaddr offset,
}
}
+static void vigs_register_capture_request_listener(void *listener,
+ void (*handler)(void *))
+{
+ return vigs_qt5_register_capture_request_listener(listener, handler);
+}
+
+static void vigs_unregister_capture_request_listener(void *listener)
+{
+ return vigs_qt5_unregister_capture_request_listener(listener);
+}
+
+static void vigs_process_captured(bool captured, void *pixels,
+ uint32_t width, uint32_t height)
+{
+ return vigs_qt5_process_captured(captured, pixels, width, height);
+}
+
static struct GraphicHwOps vigs_hw_ops =
{
.invalidate = vigs_hw_invalidate,
@@ -319,6 +336,13 @@ static struct vigs_display_ops vigs_dpy_ops =
.fence_ack = vigs_fence_ack,
};
+static struct vigs_onscreen_server_capture_ops vigs_capture_ops =
+{
+ .register_listener = vigs_register_capture_request_listener,
+ .unregister_listener = vigs_unregister_capture_request_listener,
+ .process_captured = vigs_process_captured,
+};
+
static int vigs_device_init(PCIDevice *dev)
{
VIGSState *s = DO_UPCAST(VIGSState, dev, dev);
@@ -457,6 +481,7 @@ static int vigs_device_init(PCIDevice *dev)
memory_region_get_ram_ptr(&s->ram_bar),
&vigs_dpy_ops,
s,
+ &vigs_capture_ops,
backend,
wqobj->wq);
} else {
diff --git a/hw/vigs/vigs_gl_backend.c b/hw/vigs/vigs_gl_backend.c
index 24f8b16b78..d80db57170 100644
--- a/hw/vigs/vigs_gl_backend.c
+++ b/hw/vigs/vigs_gl_backend.c
@@ -2234,6 +2234,44 @@ out:
return false;
}
+static bool vigs_gl_backend_capture(struct vigs_surface *surface,
+ void *pixels)
+{
+ struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)surface->backend;
+
+ if (gl_backend->read_pixels_make_current(gl_backend, true)) {
+
+ if (!gl_backend->dpy_fb) {
+ gl_backend->GenFramebuffers(1, &gl_backend->dpy_fb);
+
+ if (!gl_backend->dpy_fb) {
+ VIGS_LOG_ERROR("cannot create capture FB");
+
+ gl_backend->read_pixels_make_current(gl_backend, false);
+
+ return false;
+ }
+
+ }
+
+ gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb);
+ gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, gl_backend->dpy_tex, 0);
+
+ gl_backend->ReadPixels(0, 0, gl_backend->dpy_tex_width,
+ gl_backend->dpy_tex_height,
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ pixels);
+ gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ gl_backend->read_pixels_make_current(gl_backend, false);
+
+ return true;
+ }
+
+ return false;
+}
+
static void vigs_gl_backend_batch_end(struct vigs_backend *backend)
{
struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)backend;
@@ -2623,6 +2661,7 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend)
gl_backend->base.batch_start = &vigs_gl_backend_batch_start;
gl_backend->base.create_surface = &vigs_gl_backend_create_surface;
gl_backend->base.composite = &vigs_gl_backend_composite;
+ gl_backend->base.capture = &vigs_gl_backend_capture;
gl_backend->base.batch_end = &vigs_gl_backend_batch_end;
gl_backend->base.display = &vigs_gl_backend_display;
diff --git a/hw/vigs/vigs_gl_backend_glx.c b/hw/vigs/vigs_gl_backend_glx.c
index 4306420d66..b065dd977c 100644
--- a/hw/vigs/vigs_gl_backend_glx.c
+++ b/hw/vigs/vigs_gl_backend_glx.c
@@ -552,6 +552,19 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
if (!config) {
goto fail2;
}
+
+ if (!vigs_gl_backend_glx_create_surface(gl_backend_glx,
+ config,
+ &gl_backend_glx->read_pixels_sfc)) {
+ goto fail2;
+ }
+
+ if (!vigs_gl_backend_glx_create_context(gl_backend_glx,
+ config,
+ gl_backend_glx->ctx,
+ &gl_backend_glx->read_pixels_ctx)) {
+ goto fail2;
+ }
} else {
config = vigs_gl_backend_glx_get_config(gl_backend_glx);
diff --git a/hw/vigs/vigs_onscreen_server.c b/hw/vigs/vigs_onscreen_server.c
index 984fd1bed2..8a06219b26 100644
--- a/hw/vigs/vigs_onscreen_server.c
+++ b/hw/vigs/vigs_onscreen_server.c
@@ -29,6 +29,33 @@
#include "vigs_onscreen_server.h"
#include "vigs_backend.h"
+#include "vigs_log.h"
+#include "work_queue.h"
+
+struct vigs_capture_work_item
+{
+ struct work_queue_item base;
+
+ struct vigs_onscreen_server *server;
+};
+
+static void vigs_onscreen_server_capture_work(struct work_queue_item *wq_item)
+{
+ struct vigs_capture_work_item *item = (struct vigs_capture_work_item*)wq_item;
+ struct vigs_onscreen_server *server = item->server;
+ struct vigs_surface *root_sfc = server->base.root_sfc;
+ bool captured = false;
+ uint32_t width, height;
+ void *pixels;
+
+ pixels = vigs_server_get_capture_buffer(&server->base, &width, &height);
+ if (root_sfc && pixels) {
+ captured = server->base.backend->capture(root_sfc, pixels);
+ }
+ server->capture_ops->process_captured(captured, pixels, width, height);
+
+ g_free(item);
+}
static bool vigs_onscreen_server_begin_update(struct vigs_server *server,
bool is_capturing,
@@ -136,11 +163,27 @@ static bool vigs_onscreen_server_display(struct vigs_server *server,
return false;
}
+static void vigs_onscreen_server_capture(void *data)
+{
+ struct vigs_onscreen_server *server = (struct vigs_onscreen_server*)data;
+ struct vigs_capture_work_item *item;
+
+ item = g_malloc(sizeof(*item));
+
+ work_queue_item_init(&item->base, &vigs_onscreen_server_capture_work);
+
+ item->server = server;
+
+ work_queue_add_item(server->capture_queue, &item->base);
+}
+
static void vigs_onscreen_server_destroy(struct vigs_server *server)
{
struct vigs_onscreen_server *onscreen_server =
(struct vigs_onscreen_server*)server;
+ onscreen_server->capture_ops->unregister_listener(onscreen_server);
+
qemu_cond_destroy(&onscreen_server->cond);
qemu_mutex_destroy(&onscreen_server->mutex);
@@ -153,6 +196,7 @@ struct vigs_server *vigs_onscreen_server_create(uint8_t *vram_ptr,
uint8_t *ram_ptr,
struct vigs_display_ops *display_ops,
void *display_user_data,
+ struct vigs_onscreen_server_capture_ops *capture_ops,
struct vigs_backend *backend,
struct work_queue *render_queue)
{
@@ -175,5 +219,10 @@ struct vigs_server *vigs_onscreen_server_create(uint8_t *vram_ptr,
server->base.display = &vigs_onscreen_server_display;
server->base.destroy = &vigs_onscreen_server_destroy;
+ server->capture_queue = work_queue_create("capture_queue");
+ server->capture_ops = capture_ops;
+ server->capture_ops->register_listener(server,
+ vigs_onscreen_server_capture);
+
return &server->base;
}
diff --git a/hw/vigs/vigs_onscreen_server.h b/hw/vigs/vigs_onscreen_server.h
index a3b443332c..57e6abeaad 100644
--- a/hw/vigs/vigs_onscreen_server.h
+++ b/hw/vigs/vigs_onscreen_server.h
@@ -32,6 +32,17 @@
#include "vigs_server.h"
+struct vigs_onscreen_server_capture_ops
+{
+ void (*register_listener)(void */*listener*/,
+ void (*handler)(void */*listener*/));
+ void (*unregister_listener)(void */*listener*/);
+ void (*process_captured)(bool /*captured*/,
+ void */*pixels*/,
+ uint32_t /*width*/,
+ uint32_t /*height*/);
+};
+
struct vigs_onscreen_server
{
struct vigs_server base;
@@ -43,12 +54,16 @@ struct vigs_onscreen_server
bool dirty;
int invalidate_cnt;
+
+ struct vigs_onscreen_server_capture_ops *capture_ops;
+ struct work_queue *capture_queue;
};
struct vigs_server *vigs_onscreen_server_create(uint8_t *vram_ptr,
uint8_t *ram_ptr,
struct vigs_display_ops *display_ops,
void *display_user_data,
+ struct vigs_onscreen_server_capture_ops *capture_ops,
struct vigs_backend *backend,
struct work_queue *render_queue);
diff --git a/hw/vigs/vigs_qt5.cpp b/hw/vigs/vigs_qt5.cpp
index 2df737510f..e31184dc16 100644
--- a/hw/vigs/vigs_qt5.cpp
+++ b/hw/vigs/vigs_qt5.cpp
@@ -38,6 +38,12 @@ extern QApplication *qt5App;
extern QOpenGLContext *qt5GLContext;
extern QSurfaceFormat qt5GLFormat;
+extern void qt5_register_capture_request_listener(void *listener,
+ void (*handler)(void *));
+extern void qt5_unregister_capture_request_listener(void *listener);
+extern void qt5_process_captured(bool captured, void *pixels,
+ int width, int height);
+
bool vigs_qt5_enabled(void)
{
return qt5App != NULL;
@@ -138,3 +144,20 @@ void *vigs_qt5_gl_context_create(bool is_gl2)
return ret;
}
+
+void vigs_qt5_register_capture_request_listener(void *listener,
+ void (*handler)(void *))
+{
+ qt5_register_capture_request_listener(listener, handler);
+}
+
+void vigs_qt5_unregister_capture_request_listener(void *listener)
+{
+ qt5_unregister_capture_request_listener(listener);
+}
+
+void vigs_qt5_process_captured(bool captured, void *pixels,
+ int width, int height)
+{
+ qt5_process_captured(captured, pixels, width, height);
+}
diff --git a/hw/vigs/vigs_qt5.h b/hw/vigs/vigs_qt5.h
index 741cf56197..57b4a5b690 100644
--- a/hw/vigs/vigs_qt5.h
+++ b/hw/vigs/vigs_qt5.h
@@ -40,6 +40,12 @@ void *vigs_qt5_display(void);
void *vigs_qt5_gl_context_create(bool is_gl2);
+void vigs_qt5_register_capture_request_listener(void *listener,
+ void (*handler)(void *));
+void vigs_qt5_unregister_capture_request_listener(void *listener);
+void vigs_qt5_process_captured(bool captured, void *pixels,
+ int width, int height);
+
#ifdef __cplusplus
};
#endif
diff --git a/hw/vigs/vigs_server.c b/hw/vigs/vigs_server.c
index 4839e69f5d..50488f9d39 100644
--- a/hw/vigs/vigs_server.c
+++ b/hw/vigs/vigs_server.c
@@ -771,6 +771,17 @@ bool vigs_server_display(struct vigs_server *server, bool *displayed)
return server->display(server, displayed);
}
+void *vigs_server_get_capture_buffer(struct vigs_server *server,
+ uint32_t *width, uint32_t *height)
+{
+ int index = (&server->capture_buffers[0] == server->captured) ? 1 : 0;
+
+ *width = server->capture_buffers[index].width;
+ *height = server->capture_buffers[index].height;
+
+ return server->capture_buffers[index].data;
+}
+
bool vigs_server_process_captured(struct vigs_server *server, bool force)
{
bool updated = false;
diff --git a/hw/vigs/vigs_server.h b/hw/vigs/vigs_server.h
index 5c2248510b..8b6af81363 100644
--- a/hw/vigs/vigs_server.h
+++ b/hw/vigs/vigs_server.h
@@ -148,6 +148,9 @@ bool vigs_server_update_display(struct vigs_server *server, int invalidate_cnt);
bool vigs_server_display(struct vigs_server *server, bool *displayed);
+void *vigs_server_get_capture_buffer(struct vigs_server *server,
+ uint32_t *width, uint32_t *height);
+
/*
* For internal use only.
* @{
diff --git a/hw/vigs/vigs_sw_backend.c b/hw/vigs/vigs_sw_backend.c
index fa8cfb8566..2261ebcb71 100644
--- a/hw/vigs/vigs_sw_backend.c
+++ b/hw/vigs/vigs_sw_backend.c
@@ -401,6 +401,14 @@ static bool vigs_sw_backend_composite(struct vigs_surface *surface,
return true;
}
+static bool vigs_sw_backend_capture(struct vigs_surface *surface,
+ void *pixels)
+{
+ vigs_sw_backend_composite(surface, NULL, false, pixels);
+
+ return true;
+}
+
static void vigs_sw_backend_batch_end(struct vigs_backend *backend)
{
}
@@ -430,6 +438,7 @@ struct vigs_backend *vigs_sw_backend_create(void)
backend->base.batch_start = &vigs_sw_backend_batch_start;
backend->base.create_surface = &vigs_sw_backend_create_surface;
backend->base.composite = &vigs_sw_backend_composite;
+ backend->base.capture = &vigs_sw_backend_capture;
backend->base.batch_end = &vigs_sw_backend_batch_end;
backend->base.display = &vigs_sw_backend_display;
backend->base.destroy = &vigs_sw_backend_destroy;
diff --git a/tizen/src/display/qt5_supplement.cpp b/tizen/src/display/qt5_supplement.cpp
index b5bb7188ca..b21bc447e1 100644
--- a/tizen/src/display/qt5_supplement.cpp
+++ b/tizen/src/display/qt5_supplement.cpp
@@ -55,6 +55,9 @@ QApplication *qt5App = NULL;
static int argc = 0;
static char *argv[0];
+static void *captureRequestListener;
+static void (*captureRequestHandler)(void *);
+
static MainWindow *mainwindow;
static UIInformation *uiInfo;
@@ -173,6 +176,7 @@ void qt5_gui_init(void)
qDebug("start!");
mainwindow = new MainWindow(uiInfo);
+ mainwindow->setCaptureRequestHandler(captureRequestListener, captureRequestHandler);
/* position */
QRect hostBounds = UIUtil::getHostScreenBounds();
@@ -288,6 +292,33 @@ void qt5_refresh_internal(void)
qt5App->processEvents();
}
+void qt5_register_capture_request_listener(void *listener, void (*handler)(void *))
+{
+ if (mainwindow) {
+ mainwindow->setCaptureRequestHandler(listener, handler);
+ }
+
+ captureRequestListener = listener;
+ captureRequestHandler = handler;
+}
+
+void qt5_unregister_capture_request_listener(void *listener)
+{
+ if (mainwindow) {
+ mainwindow->unsetCaptureRequestHandler(listener);
+ }
+
+ captureRequestListener = NULL;
+ captureRequestHandler = NULL;
+}
+
+void qt5_process_captured(bool captured, void *pixels, int width, int height)
+{
+ if (mainwindow) {
+ mainwindow->processCaptured(captured, pixels, width, height);
+ }
+}
+
void qMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
diff --git a/tizen/src/ui/mainwindow.cpp b/tizen/src/ui/mainwindow.cpp
index c00cc2dd36..d514824774 100644
--- a/tizen/src/ui/mainwindow.cpp
+++ b/tizen/src/ui/mainwindow.cpp
@@ -81,6 +81,9 @@ MainWindow::MainWindow(UIInformation *uiInfo, QWidget *parent)
skinView = NULL;
display = NULL;
+ captureRequestHandler = NULL;
+ captureRequestData = NULL;
+
/* windowing */
setWindowTitle("Emulator");
setWindowIcon(QIcon(QPixmap(":/icons/emulator_icon.ico")));
@@ -323,6 +326,45 @@ void MainWindow::scale(int scale)
adjustSize();
}
+void MainWindow::capture(void)
+{
+ qDebug("window screen capture: handler(%p), data(%p)",
+ captureRequestHandler, captureRequestData);
+
+ if (captureRequestHandler && captureRequestData) {
+ captureRequestHandler(captureRequestData);
+ }
+}
+
+void MainWindow::setCaptureRequestHandler(void *data, void (*handler)(void *))
+{
+ captureRequestHandler = handler;
+ captureRequestData = data;
+}
+
+void MainWindow::unsetCaptureRequestHandler(void *data)
+{
+ captureRequestHandler = NULL;
+ captureRequestData = NULL;
+}
+
+void MainWindow::processCaptured(bool captured, void *pixels,
+ int width, int height)
+{
+ qDebug("window process captured: %d %p[%dx%d]",
+ captured, pixels, width, height);
+
+ if (captured) {
+ /* TODO Perform what is needed here */
+ QString path("/tmp/screenshot.png");
+ QImage image = QImage((uchar *)pixels, width, height,
+ QImage::Format_RGB32);
+ bool saved = image.save(path, "PNG");
+
+ qDebug() << path << " " << saved;
+ }
+}
+
void MainWindow::setTopMost(bool on)
{
popupMenu->slotTopMost(on);
diff --git a/tizen/src/ui/mainwindow.h b/tizen/src/ui/mainwindow.h
index 4a636403dc..6b50dcec6b 100644
--- a/tizen/src/ui/mainwindow.h
+++ b/tizen/src/ui/mainwindow.h
@@ -76,6 +76,10 @@ public:
UIState *getUIState(void);
void rotate(int angle);
void scale(int scale);
+ void capture(void);
+ void setCaptureRequestHandler(void *data, void (*handler)(void *));
+ void unsetCaptureRequestHandler(void *data);
+ void processCaptured(bool captured, void *pixels, int width, int height);
void setTopMost(bool on);
DockingController *getDockingCon();
FloatingController *getFloatingCon();
@@ -107,6 +111,9 @@ private:
QThread *swapperThread;
DisplaySwapper *swapper;
+
+ void (*captureRequestHandler)(void *data);
+ void *captureRequestData;
};
#endif // MAINWINDOW_H
diff --git a/tizen/src/ui/menu/contextmenu.cpp b/tizen/src/ui/menu/contextmenu.cpp
index aebfac4eba..82a19c3128 100644
--- a/tizen/src/ui/menu/contextmenu.cpp
+++ b/tizen/src/ui/menu/contextmenu.cpp
@@ -179,12 +179,10 @@ void ContextMenu::createItems() {
/* = Advanced menu = */
QMenu *advancedMenu = addMenu(QIcon(QPixmap(":/icons/advanced.png")), "Ad&vanced");
-#if 0
/* Advanced > Screen Shot menu */
action = advancedMenu->addAction("Screen Shot");
action->setIcon(QIcon(QPixmap(":/icons/screen_shot.png")));
- // TODO:
-#endif
+ connect(action, SIGNAL(triggered()), this, SLOT(slotScreenshot()));
/* = Host Keyboard menu = */
QMenu *keyboardMenu = advancedMenu->addMenu(
@@ -470,6 +468,13 @@ void ContextMenu::slotControlPanel()
}
}
+void ContextMenu::slotScreenshot()
+{
+ qDebug("screenshot");
+
+ parent->capture();
+}
+
void ContextMenu::slotHostKeyboard(bool on)
{
qDebug("host keyboard : %s", on? "on" : "off");
diff --git a/tizen/src/ui/menu/contextmenu.h b/tizen/src/ui/menu/contextmenu.h
index 2edb4321ce..a8e4212f88 100644
--- a/tizen/src/ui/menu/contextmenu.h
+++ b/tizen/src/ui/menu/contextmenu.h
@@ -69,6 +69,7 @@ public slots:
void slotCloseCon();
void slotShell();
void slotControlPanel();
+ void slotScreenshot();
void slotHostKeyboard(bool on);
void slotAbout();
void slotForceClose();