OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chromecast/ui/gfx/gfx_plane_directfb.h" |
| 6 |
| 7 #include <string> |
| 8 #include <vector> |
| 9 |
| 10 #include "base/command_line.h" |
| 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "chromecast/ui/gfx/surface_directfb.h" |
| 14 #include "ui/gfx/rect.h" |
| 15 #include "ui/gfx/size.h" |
| 16 |
| 17 namespace gfx { |
| 18 namespace chromecast { |
| 19 |
| 20 // DirectFB on X11 notes: |
| 21 // |
| 22 // 1. There is a thread created at launch to intercept X11 input events |
| 23 // "x11EventThread". |
| 24 // |
| 25 // 2. If you close a window created by DirectFB on X11 (via mouse), and |
| 26 // continue to do directfb calls, the program will crash: |
| 27 // |
| 28 // XIO: fatal IO error 11 (Resource temporarily unavailable) ... |
| 29 // after 333 requests (301 known processed) with 0 events ... |
| 30 // (!!!) *** WARNING [Application exited without deinitialization ... |
| 31 // Segmentation fault |
| 32 // |
| 33 // This should normally be handled by the X11EventThread. It should |
| 34 // receive a WM_DELETE_WINDOW (from X11) and post a directfb event |
| 35 // DWET_CLOSE or DWET_DESTROYED. This should in turn be handled by a directfb |
| 36 // event listener loop (which we could implement). |
| 37 // |
| 38 // Unfortunately, in DFB 1.2, the X11Eventthread only seems to handle and pass |
| 39 // on key and mouse events. So, we are stuck with program crashes when a user |
| 40 // closes a window (unless we want to write our own X11 listener or fix DFB). |
| 41 // |
| 42 GfxPlaneDirectFb::GfxPlaneDirectFb(const base::CommandLine& command_line) { |
| 43 const std::vector<std::string>& args = command_line.argv(); |
| 44 int argc = args.size(); |
| 45 scoped_ptr<char *[]> argv(new char *[argc + 1]); |
| 46 for (size_t i = 0; i < args.size(); ++i) { |
| 47 argv[i] = strdup(args[i].c_str()); |
| 48 } |
| 49 argv[argc] = NULL; |
| 50 char **argv_pointer = argv.get(); |
| 51 |
| 52 // using a copy of arguments so they aren't modified. |
| 53 |
| 54 // Note: DirectFBInit *will* modify the arguments |
| 55 |
| 56 // Note: there are lots of DFB arguments |
| 57 // see --dfb-help for list |
| 58 // pass them via --dfb:<option>[,<option>] |
| 59 // ex: session=0 (MVGFX on Marvell) |
| 60 // mode=1920x1080 (not needed) |
| 61 DFBResult err = DirectFBInit(&argc, &argv_pointer); |
| 62 |
| 63 for (size_t i = 0; i < args.size(); ++i) { |
| 64 free(argv[i]); |
| 65 } |
| 66 |
| 67 if (err != DFB_OK) { // test err from init above |
| 68 LOG(FATAL) << "DirectFBInit failed, err = " << DirectFBErrorString(err); |
| 69 } |
| 70 |
| 71 // When single-buffered, and we set this option: |
| 72 // |
| 73 // DirectFBSetOption ("autoflip-window", NULL); |
| 74 // |
| 75 // Directfb will create a "Flipping Thread". We'll just flip outselves |
| 76 // and save the overhead. This will emit an error which we can ignore: |
| 77 // |
| 78 // (!!!) *** WARNING [Non-flipping window surface and no ... |
| 79 // 'autoflip-window' option used] *** |
| 80 |
| 81 err = DirectFBCreate(&dfb_); |
| 82 if (err != DFB_OK) { |
| 83 LOG(FATAL) << "DirectFBCreate failed, err = " << DirectFBErrorString(err); |
| 84 } |
| 85 |
| 86 err = dfb_->SetCooperativeLevel(dfb_, |
| 87 #if defined(__arm__) |
| 88 DFSCL_EXCLUSIVE |
| 89 #else |
| 90 DFSCL_FULLSCREEN |
| 91 #endif |
| 92 ); |
| 93 if (err != DFB_OK) { |
| 94 #if defined(__arm__) |
| 95 LOG(FATAL) |
| 96 #else |
| 97 LOG(WARNING) |
| 98 #endif |
| 99 << "Set EXCLUSIVE/FULLSCREEN failed, err = " |
| 100 << DirectFBErrorString(err); |
| 101 } |
| 102 } |
| 103 |
| 104 // Shutdown directfb. Under X11, this will also close the window. |
| 105 // |
| 106 // These messages may appear on the console: |
| 107 // |
| 108 // (!!!) *** WARNING [still objects in 'GraphicsState Pool'] *** ... |
| 109 // (!!!) *** WARNING [still objects in 'Surface Pool'] *** ... |
| 110 // |
| 111 |
| 112 // Note2: This function crashes under DFB 1.2.8 on Linux due to memory |
| 113 // corruption. Valgind shows there are multiple malloc/free problems with |
| 114 // DFB 1.2.8. DFB 1.5.3 runs cleanly with valgrind (and doesn't crash). |
| 115 GfxPlaneDirectFb::~GfxPlaneDirectFb() { |
| 116 set_frame_buffer(NULL); // Release frame buffer here before closing DFB. |
| 117 dfb_->Release(dfb_); |
| 118 } |
| 119 |
| 120 Surface* GfxPlaneDirectFb::CreateSurface(const gfx::Size& arg_size) { |
| 121 return new SurfaceDirectFb(this, arg_size, false); |
| 122 } |
| 123 |
| 124 // static |
| 125 GfxPlane* GfxPlane::CreatePrimary(const base::CommandLine& command_line, |
| 126 const Size& requested_screen_size) { |
| 127 #if defined(__arm__) |
| 128 CHECK(!primary_); |
| 129 #else |
| 130 // On x86, we don't destroy gfx plane because directfd crashes. |
| 131 if (primary_) return primary_; |
| 132 #endif |
| 133 |
| 134 GfxPlaneDirectFb* directfb = new GfxPlaneDirectFb(command_line); |
| 135 directfb->set_frame_buffer( |
| 136 new SurfaceDirectFb(directfb, directfb->size(), true)); |
| 137 |
| 138 primary_ = directfb; |
| 139 return primary_; |
| 140 } |
| 141 |
| 142 // static |
| 143 void GfxPlane::DestroyPrimary() { |
| 144 CHECK(primary_); |
| 145 #if defined(__arm__) |
| 146 delete primary_; |
| 147 // primary_ = NULL; already reset by dtor(). |
| 148 #endif |
| 149 } |
| 150 |
| 151 // static |
| 152 GfxPlane* GfxPlane::CreateOsdPlane() { |
| 153 // Use primary gfx plane for OSD. |
| 154 // Do nothing here. |
| 155 return primary_; |
| 156 } |
| 157 |
| 158 // static |
| 159 void GfxPlane::DestroyOsdPlane() { |
| 160 // Use primary gfx plane for OSD. |
| 161 // Do nothing here. |
| 162 } |
| 163 |
| 164 // static |
| 165 GfxPlane* GfxPlane::GetOsdPlane() { |
| 166 return primary_; |
| 167 } |
| 168 |
| 169 // static |
| 170 void GfxPlane::ResizeOsdPlane(const Size& size) { |
| 171 // Use primary gfx plane for OSD. |
| 172 // Do nothing here. |
| 173 } |
| 174 |
| 175 // static |
| 176 bool GfxPlane::Is1080pAllowed() { |
| 177 return true; |
| 178 } |
| 179 |
| 180 } // namespace chromecast |
| 181 } // namespace gfx |
OLD | NEW |