Index: chromecast/ui/gfx/gfx_plane_directfb.cc |
diff --git a/chromecast/ui/gfx/gfx_plane_directfb.cc b/chromecast/ui/gfx/gfx_plane_directfb.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9e509ac1b886f5ce0451dd04981655f3334b3e18 |
--- /dev/null |
+++ b/chromecast/ui/gfx/gfx_plane_directfb.cc |
@@ -0,0 +1,181 @@ |
+// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chromecast/ui/gfx/gfx_plane_directfb.h" |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/command_line.h" |
+#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "chromecast/ui/gfx/surface_directfb.h" |
+#include "ui/gfx/rect.h" |
+#include "ui/gfx/size.h" |
+ |
+namespace gfx { |
+namespace chromecast { |
+ |
+// DirectFB on X11 notes: |
+// |
+// 1. There is a thread created at launch to intercept X11 input events |
+// "x11EventThread". |
+// |
+// 2. If you close a window created by DirectFB on X11 (via mouse), and |
+// continue to do directfb calls, the program will crash: |
+// |
+// XIO: fatal IO error 11 (Resource temporarily unavailable) ... |
+// after 333 requests (301 known processed) with 0 events ... |
+// (!!!) *** WARNING [Application exited without deinitialization ... |
+// Segmentation fault |
+// |
+// This should normally be handled by the X11EventThread. It should |
+// receive a WM_DELETE_WINDOW (from X11) and post a directfb event |
+// DWET_CLOSE or DWET_DESTROYED. This should in turn be handled by a directfb |
+// event listener loop (which we could implement). |
+// |
+// Unfortunately, in DFB 1.2, the X11Eventthread only seems to handle and pass |
+// on key and mouse events. So, we are stuck with program crashes when a user |
+// closes a window (unless we want to write our own X11 listener or fix DFB). |
+// |
+GfxPlaneDirectFb::GfxPlaneDirectFb(const base::CommandLine& command_line) { |
+ const std::vector<std::string>& args = command_line.argv(); |
+ int argc = args.size(); |
+ scoped_ptr<char *[]> argv(new char *[argc + 1]); |
+ for (size_t i = 0; i < args.size(); ++i) { |
+ argv[i] = strdup(args[i].c_str()); |
+ } |
+ argv[argc] = NULL; |
+ char **argv_pointer = argv.get(); |
+ |
+ // using a copy of arguments so they aren't modified. |
+ |
+ // Note: DirectFBInit *will* modify the arguments |
+ |
+ // Note: there are lots of DFB arguments |
+ // see --dfb-help for list |
+ // pass them via --dfb:<option>[,<option>] |
+ // ex: session=0 (MVGFX on Marvell) |
+ // mode=1920x1080 (not needed) |
+ DFBResult err = DirectFBInit(&argc, &argv_pointer); |
+ |
+ for (size_t i = 0; i < args.size(); ++i) { |
+ free(argv[i]); |
+ } |
+ |
+ if (err != DFB_OK) { // test err from init above |
+ LOG(FATAL) << "DirectFBInit failed, err = " << DirectFBErrorString(err); |
+ } |
+ |
+ // When single-buffered, and we set this option: |
+ // |
+ // DirectFBSetOption ("autoflip-window", NULL); |
+ // |
+ // Directfb will create a "Flipping Thread". We'll just flip outselves |
+ // and save the overhead. This will emit an error which we can ignore: |
+ // |
+ // (!!!) *** WARNING [Non-flipping window surface and no ... |
+ // 'autoflip-window' option used] *** |
+ |
+ err = DirectFBCreate(&dfb_); |
+ if (err != DFB_OK) { |
+ LOG(FATAL) << "DirectFBCreate failed, err = " << DirectFBErrorString(err); |
+ } |
+ |
+ err = dfb_->SetCooperativeLevel(dfb_, |
+#if defined(__arm__) |
+ DFSCL_EXCLUSIVE |
+#else |
+ DFSCL_FULLSCREEN |
+#endif |
+ ); |
+ if (err != DFB_OK) { |
+#if defined(__arm__) |
+ LOG(FATAL) |
+#else |
+ LOG(WARNING) |
+#endif |
+ << "Set EXCLUSIVE/FULLSCREEN failed, err = " |
+ << DirectFBErrorString(err); |
+ } |
+} |
+ |
+// Shutdown directfb. Under X11, this will also close the window. |
+// |
+// These messages may appear on the console: |
+// |
+// (!!!) *** WARNING [still objects in 'GraphicsState Pool'] *** ... |
+// (!!!) *** WARNING [still objects in 'Surface Pool'] *** ... |
+// |
+ |
+// Note2: This function crashes under DFB 1.2.8 on Linux due to memory |
+// corruption. Valgind shows there are multiple malloc/free problems with |
+// DFB 1.2.8. DFB 1.5.3 runs cleanly with valgrind (and doesn't crash). |
+GfxPlaneDirectFb::~GfxPlaneDirectFb() { |
+ set_frame_buffer(NULL); // Release frame buffer here before closing DFB. |
+ dfb_->Release(dfb_); |
+} |
+ |
+Surface* GfxPlaneDirectFb::CreateSurface(const gfx::Size& arg_size) { |
+ return new SurfaceDirectFb(this, arg_size, false); |
+} |
+ |
+// static |
+GfxPlane* GfxPlane::CreatePrimary(const base::CommandLine& command_line, |
+ const Size& requested_screen_size) { |
+#if defined(__arm__) |
+ CHECK(!primary_); |
+#else |
+ // On x86, we don't destroy gfx plane because directfd crashes. |
+ if (primary_) return primary_; |
+#endif |
+ |
+ GfxPlaneDirectFb* directfb = new GfxPlaneDirectFb(command_line); |
+ directfb->set_frame_buffer( |
+ new SurfaceDirectFb(directfb, directfb->size(), true)); |
+ |
+ primary_ = directfb; |
+ return primary_; |
+} |
+ |
+// static |
+void GfxPlane::DestroyPrimary() { |
+ CHECK(primary_); |
+#if defined(__arm__) |
+ delete primary_; |
+ // primary_ = NULL; already reset by dtor(). |
+#endif |
+} |
+ |
+// static |
+GfxPlane* GfxPlane::CreateOsdPlane() { |
+ // Use primary gfx plane for OSD. |
+ // Do nothing here. |
+ return primary_; |
+} |
+ |
+// static |
+void GfxPlane::DestroyOsdPlane() { |
+ // Use primary gfx plane for OSD. |
+ // Do nothing here. |
+} |
+ |
+// static |
+GfxPlane* GfxPlane::GetOsdPlane() { |
+ return primary_; |
+} |
+ |
+// static |
+void GfxPlane::ResizeOsdPlane(const Size& size) { |
+ // Use primary gfx plane for OSD. |
+ // Do nothing here. |
+} |
+ |
+// static |
+bool GfxPlane::Is1080pAllowed() { |
+ return true; |
+} |
+ |
+} // namespace chromecast |
+} // namespace gfx |