|
@@ -1249,6 +1249,43 @@ texture_uploaded(Texture *tex) {
|
|
|
// Usually only called by DisplayRegion::do_cull.
|
|
// Usually only called by DisplayRegion::do_cull.
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Called by DisplayRegion::do_get_screenshot
|
|
|
|
|
+ */
|
|
|
|
|
+PT(Texture) GraphicsEngine::
|
|
|
|
|
+do_get_screenshot(DisplayRegion *region, GraphicsStateGuardian *gsg) {
|
|
|
|
|
+ // A multi-threaded environment. We have to wait until the draw thread
|
|
|
|
|
+ // has finished its current task.
|
|
|
|
|
+
|
|
|
|
|
+ ReMutexHolder holder(_lock);
|
|
|
|
|
+
|
|
|
|
|
+ const std::string &draw_name = gsg->get_threading_model().get_draw_name();
|
|
|
|
|
+ WindowRenderer *wr = get_window_renderer(draw_name, 0);
|
|
|
|
|
+ RenderThread *thread = (RenderThread *)wr;
|
|
|
|
|
+ MutexHolder cv_holder(thread->_cv_mutex);
|
|
|
|
|
+
|
|
|
|
|
+ while (thread->_thread_state != TS_wait) {
|
|
|
|
|
+ thread->_cv_done.wait();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Now that the draw thread is idle, signal it to do the extraction task.
|
|
|
|
|
+ thread->_region = region;
|
|
|
|
|
+ thread->_thread_state = TS_do_screenshot;
|
|
|
|
|
+ thread->_cv_start.notify();
|
|
|
|
|
+ thread->_cv_mutex.release();
|
|
|
|
|
+ thread->_cv_mutex.acquire();
|
|
|
|
|
+
|
|
|
|
|
+ //XXX is this necessary, or is acquiring the mutex enough?
|
|
|
|
|
+ while (thread->_thread_state != TS_wait) {
|
|
|
|
|
+ thread->_cv_done.wait();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ PT(Texture) tex = std::move(thread->_texture);
|
|
|
|
|
+ thread->_region = nullptr;
|
|
|
|
|
+ thread->_texture = nullptr;
|
|
|
|
|
+ return tex;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Fires off a cull traversal using the indicated camera.
|
|
* Fires off a cull traversal using the indicated camera.
|
|
|
*/
|
|
*/
|
|
@@ -2633,6 +2670,11 @@ thread_main() {
|
|
|
_result = _gsg->extract_texture_data(_texture);
|
|
_result = _gsg->extract_texture_data(_texture);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
|
|
+ case TS_do_screenshot:
|
|
|
|
|
+ nassertd(_region != nullptr) break;
|
|
|
|
|
+ _texture = _region->get_screenshot();
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
case TS_terminate:
|
|
case TS_terminate:
|
|
|
do_pending(_engine, current_thread);
|
|
do_pending(_engine, current_thread);
|
|
|
do_close(_engine, current_thread);
|
|
do_close(_engine, current_thread);
|