Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: plugin/mac/main_mac.mm

Issue 149130: In preparation for becoming an internal plugin in chrome I did these things:... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/o3d/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2009, Google Inc. 2 * Copyright 2009, Google Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 #include <AGL/aglRenderers.h> 47 #include <AGL/aglRenderers.h>
48 48
49 #include "core/cross/event.h" 49 #include "core/cross/event.h"
50 #include "statsreport/metrics.h" 50 #include "statsreport/metrics.h"
51 #include "plugin/cross/plugin_logging.h" 51 #include "plugin/cross/plugin_logging.h"
52 #include "plugin/cross/plugin_metrics.h" 52 #include "plugin/cross/plugin_metrics.h"
53 #include "plugin/cross/out_of_memory.h" 53 #include "plugin/cross/out_of_memory.h"
54 #include "plugin/mac/plugin_mac.h" 54 #include "plugin/mac/plugin_mac.h"
55 #include "plugin/mac/graphics_utils_mac.h" 55 #include "plugin/mac/graphics_utils_mac.h"
56 56
57 57 #if !defined(O3D_INTERNAL_PLUGIN)
58 o3d::PluginLogging* g_logger = NULL; 58 o3d::PluginLogging* g_logger = NULL;
59 bool g_logging_initialized = false; 59 bool g_logging_initialized = false;
60 #endif
60 61
61 using glue::_o3d::PluginObject; 62 using glue::_o3d::PluginObject;
62 using glue::StreamManager; 63 using glue::StreamManager;
63 using o3d::DisplayWindowMac; 64 using o3d::DisplayWindowMac;
64 using o3d::Event; 65 using o3d::Event;
65 66
66 namespace { 67 namespace {
67 // We would normally make this a stack variable in main(), but in a 68 // We would normally make this a stack variable in main(), but in a
68 // plugin, that's not possible, so we allocate it dynamically and 69 // plugin, that's not possible, so we allocate it dynamically and
69 // destroy it explicitly. 70 // destroy it explicitly.
70 scoped_ptr<base::AtExitManager> g_at_exit_manager; 71 scoped_ptr<base::AtExitManager> g_at_exit_manager;
71 } // end anonymous namespace
72 72
73 // if defined, in AGL mode we do double buffered drawing 73 // if defined, in AGL mode we do double buffered drawing
74 // #define USE_AGL_DOUBLE_BUFFER 74 // #define USE_AGL_DOUBLE_BUFFER
75 75
76 #define CFTIMER 76 #define CFTIMER
77 // #define DEFERRED_DRAW_ON_NULLEVENTS 77 // #define DEFERRED_DRAW_ON_NULLEVENTS
78 78
79 // currently drawing with the timer doesn't play well with USE_AGL_DOUBLE_BUFFER 79 // currently drawing with the timer doesn't play well with USE_AGL_DOUBLE_BUFFER
80 #ifdef CFTIMER 80 #ifdef CFTIMER
81 #undef USE_AGL_DOUBLE_BUFFER 81 #undef USE_AGL_DOUBLE_BUFFER
82 #endif 82 #endif
83 83
84 static void DrawPlugin(PluginObject* obj) { 84 void DrawPlugin(PluginObject* obj) {
85 obj->client()->RenderClient(); 85 obj->client()->RenderClient();
86 #ifdef USE_AGL_DOUBLE_BUFFER 86 #ifdef USE_AGL_DOUBLE_BUFFER
87 // In AGL mode, we have to call aglSwapBuffers to guarantee that our 87 // In AGL mode, we have to call aglSwapBuffers to guarantee that our
88 // pixels make it to the screen. 88 // pixels make it to the screen.
89 if (obj->mac_agl_context_ != NULL) 89 if (obj->mac_agl_context_ != NULL)
90 aglSwapBuffers(obj->mac_agl_context_); 90 aglSwapBuffers(obj->mac_agl_context_);
91 #endif 91 #endif
92 } 92 }
93 93
94 void RenderOnDemandCallbackHandler::Run() { 94 unsigned char GetMacEventKeyChar(const EventRecord *the_event) {
95 obj_->SetWantsRedraw(true);
96 }
97
98 static unsigned char GetMacEventKeyChar(const EventRecord *the_event) {
99 unsigned char the_char = the_event->message & charCodeMask; 95 unsigned char the_char = the_event->message & charCodeMask;
100 return the_char; 96 return the_char;
101 } 97 }
102 98
103 static unsigned char GetMacEventKeyCode(const EventRecord *the_event) { 99 unsigned char GetMacEventKeyCode(const EventRecord *the_event) {
104 unsigned char the_key_code = (the_event->message & keyCodeMask) >> 8; 100 unsigned char the_key_code = (the_event->message & keyCodeMask) >> 8;
105 return the_key_code; 101 return the_key_code;
106 } 102 }
107 103
108 104
109 // Cocoa key events for things like arrow key presses can have strange unicode 105 // Cocoa key events for things like arrow key presses can have strange unicode
110 // values in the 0xF700-0xF747 range, eg NSUpArrowFunctionKey is 0xF700. 106 // values in the 0xF700-0xF747 range, eg NSUpArrowFunctionKey is 0xF700.
111 // These values are defined in NSEvent.h. 107 // These values are defined in NSEvent.h.
112 // Map the ones we care about to the more commonly understood values in 108 // Map the ones we care about to the more commonly understood values in
113 // the Mac system header Events.h, eg kUpArrowCharCode is 30. 109 // the Mac system header Events.h, eg kUpArrowCharCode is 30.
114 static int TranslateMacUnicodeControlChar(int theChar) { 110 int TranslateMacUnicodeControlChar(int theChar) {
115 switch(theChar) { 111 switch(theChar) {
116 case NSUpArrowFunctionKey: 112 case NSUpArrowFunctionKey:
117 return kUpArrowCharCode; 113 return kUpArrowCharCode;
118 case NSDownArrowFunctionKey: 114 case NSDownArrowFunctionKey:
119 return kDownArrowCharCode; 115 return kDownArrowCharCode;
120 case NSLeftArrowFunctionKey: 116 case NSLeftArrowFunctionKey:
121 return kLeftArrowCharCode; 117 return kLeftArrowCharCode;
122 case NSRightArrowFunctionKey: 118 case NSRightArrowFunctionKey:
123 return kRightArrowCharCode; 119 return kRightArrowCharCode;
124 } 120 }
125 return theChar; 121 return theChar;
126 } 122 }
127 123
128 124
129 // The Mac standard char codes for arrow keys are different from the 125 // The Mac standard char codes for arrow keys are different from the
130 // web standard. 126 // web standard.
131 // Also in the browser world the enter key gets mapped to be the same as the 127 // Also in the browser world the enter key gets mapped to be the same as the
132 // return key. 128 // return key.
133 static int TranslateMacControlCharToWebChar(int theChar) { 129 int TranslateMacControlCharToWebChar(int theChar) {
134 switch(theChar) { 130 switch(theChar) {
135 case kUpArrowCharCode: 131 case kUpArrowCharCode:
136 return 38; 132 return 38;
137 case kDownArrowCharCode: 133 case kDownArrowCharCode:
138 return 40; 134 return 40;
139 case kLeftArrowCharCode: 135 case kLeftArrowCharCode:
140 return 37; 136 return 37;
141 case kRightArrowCharCode: 137 case kRightArrowCharCode:
142 return 39; 138 return 39;
143 case kEnterCharCode: 139 case kEnterCharCode:
144 return kReturnCharCode; 140 return kReturnCharCode;
145 } 141 }
146 return theChar; 142 return theChar;
147 } 143 }
148 144
149 145
150 // Given an instance, and some event data, calls Javascript methods 146 // Given an instance, and some event data, calls Javascript methods
151 // placed on the object tag so that the keystrokes can be handled in 147 // placed on the object tag so that the keystrokes can be handled in
152 // Javascript. 148 // Javascript.
153 static void DispatchKeyboardEvent(PluginObject* obj, 149 void DispatchKeyboardEvent(PluginObject* obj,
154 EventKind kind, 150 EventKind kind,
155 int theChar, 151 int theChar,
156 int theKeyCode, 152 int theKeyCode,
157 EventModifiers mods) { 153 EventModifiers mods) {
158 theChar = TranslateMacUnicodeControlChar(theChar); 154 theChar = TranslateMacUnicodeControlChar(theChar);
159 theChar = TranslateMacControlCharToWebChar(theChar); 155 theChar = TranslateMacControlCharToWebChar(theChar);
160 int upperChar = (theChar >= 'a' && theChar <='z') ? theChar - 32 : theChar; 156 int upperChar = (theChar >= 'a' && theChar <='z') ? theChar - 32 : theChar;
161 157
162 Event::Type type; 158 Event::Type type;
163 switch (kind) { 159 switch (kind) {
164 case keyDown: 160 case keyDown:
165 // We'll also have to send a keypress below. 161 // We'll also have to send a keypress below.
166 type = Event::TYPE_KEYDOWN; 162 type = Event::TYPE_KEYDOWN;
167 break; 163 break;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 event.clear_key_code(); 201 event.clear_key_code();
206 event.set_char_code(theChar); 202 event.set_char_code(theChar);
207 event.set_type(Event::TYPE_KEYPRESS); 203 event.set_type(Event::TYPE_KEYPRESS);
208 obj->client()->AddEventToQueue(event); 204 obj->client()->AddEventToQueue(event);
209 } 205 }
210 } 206 }
211 207
212 // Given an instance, and a MacOS keyboard event, calls Javascript methods 208 // Given an instance, and a MacOS keyboard event, calls Javascript methods
213 // placed on the object tag so that the keystrokes can be handled in 209 // placed on the object tag so that the keystrokes can be handled in
214 // Javascript. 210 // Javascript.
215 static void DispatchMacKeyboardEvent(PluginObject* obj, 211 void DispatchMacKeyboardEvent(PluginObject* obj,
216 EventRecord* the_event) { 212 EventRecord* the_event) {
217 DispatchKeyboardEvent(obj, 213 DispatchKeyboardEvent(obj,
218 the_event->what, 214 the_event->what,
219 GetMacEventKeyChar(the_event), 215 GetMacEventKeyChar(the_event),
220 GetMacEventKeyCode(the_event), 216 GetMacEventKeyCode(the_event),
221 the_event->modifiers); 217 the_event->modifiers);
222 } 218 }
223 219
224 220
225 221
226 static void HandleMouseEvent(PluginObject* obj, 222 void HandleMouseEvent(PluginObject* obj,
227 EventRecord* the_event) { 223 EventRecord* the_event) {
228 DCHECK(obj); 224 DCHECK(obj);
229 DCHECK(obj->client()); 225 DCHECK(obj->client());
230 int screen_x = the_event->where.h; 226 int screen_x = the_event->where.h;
231 int screen_y = the_event->where.v; 227 int screen_y = the_event->where.v;
232 static Point last_mouse_loc = {0,0}; 228 static Point last_mouse_loc = {0,0};
233 229
234 o3d::Event::Type type; 230 o3d::Event::Type type;
235 switch (the_event->what) { 231 switch (the_event->what) {
236 case mouseDown: 232 case mouseDown:
237 type = o3d::Event::TYPE_MOUSEDOWN; 233 type = o3d::Event::TYPE_MOUSEDOWN;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 if (in_plugin && type == Event::TYPE_MOUSEDOWN && 294 if (in_plugin && type == Event::TYPE_MOUSEDOWN &&
299 obj->HitFullscreenClickRegion(x, y)) { 295 obj->HitFullscreenClickRegion(x, y)) {
300 obj->RequestFullscreenDisplay(); 296 obj->RequestFullscreenDisplay();
301 } 297 }
302 } 298 }
303 299
304 // Handle a mouse-related NPCocoaEvent. 300 // Handle a mouse-related NPCocoaEvent.
305 // These events come from the new Cocoa revision of the NPAPI spec, 301 // These events come from the new Cocoa revision of the NPAPI spec,
306 // currently implemented only in Safari. 302 // currently implemented only in Safari.
307 // See https://wiki.mozilla.org/Mac:NPAPI_Event_Models 303 // See https://wiki.mozilla.org/Mac:NPAPI_Event_Models
308 static void HandleCocoaMouseEvent(PluginObject* obj, 304 void HandleCocoaMouseEvent(PluginObject* obj,
309 NPCocoaEvent* the_event) { 305 NPCocoaEvent* the_event) {
310 DCHECK(obj); 306 DCHECK(obj);
311 DCHECK(obj->client()); 307 DCHECK(obj->client());
312 int screen_x = the_event->data.mouse.pluginX; 308 int screen_x = the_event->data.mouse.pluginX;
313 int screen_y = the_event->data.mouse.pluginY; 309 int screen_y = the_event->data.mouse.pluginY;
314 310
315 o3d::Event::Type type; 311 o3d::Event::Type type;
316 switch (the_event->type) { 312 switch (the_event->type) {
317 case NPCocoaEventMouseDown: 313 case NPCocoaEventMouseDown:
318 type = o3d::Event::TYPE_MOUSEDOWN; 314 type = o3d::Event::TYPE_MOUSEDOWN;
319 break; 315 break;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 the_event->data.mouse.deltaX = 0; 365 the_event->data.mouse.deltaX = 0;
370 } 366 }
371 } 367 }
372 event.set_delta(the_event->data.mouse.deltaX * 10.0, 368 event.set_delta(the_event->data.mouse.deltaX * 10.0,
373 the_event->data.mouse.deltaY * 10.0); 369 the_event->data.mouse.deltaY * 10.0);
374 } 370 }
375 371
376 if ((the_event->type == NPCocoaEventMouseDown) || 372 if ((the_event->type == NPCocoaEventMouseDown) ||
377 (the_event->type == NPCocoaEventMouseUp)) { 373 (the_event->type == NPCocoaEventMouseUp)) {
378 event.set_button( 374 event.set_button(
379 MacOSMouseButtonNumberToO3DButton( 375 o3d::MacOSMouseButtonNumberToO3DButton(
380 the_event->data.mouse.buttonNumber)); 376 the_event->data.mouse.buttonNumber));
381 } 377 }
382 378
383 event.set_position(x, y, screen_x, screen_y, in_plugin); 379 event.set_position(x, y, screen_x, screen_y, in_plugin);
384 obj->client()->AddEventToQueue(event); 380 obj->client()->AddEventToQueue(event);
385 381
386 if (in_plugin && type == Event::TYPE_MOUSEDOWN && 382 if (in_plugin && type == Event::TYPE_MOUSEDOWN &&
387 obj->HitFullscreenClickRegion(x, y)) { 383 obj->HitFullscreenClickRegion(x, y)) {
388 obj->RequestFullscreenDisplay(); 384 obj->RequestFullscreenDisplay();
389 } 385 }
390 } 386 }
391 387
392 388
393 389
394 390
395 // Convert an NSEvent style modifiers field to an EventRecord style one. 391 // Convert an NSEvent style modifiers field to an EventRecord style one.
396 // Not all bits have a representation in the target type, eg NSFunctionKeyMask 392 // Not all bits have a representation in the target type, eg NSFunctionKeyMask
397 // but we just need to convert the basic modifiers that need to be passed on 393 // but we just need to convert the basic modifiers that need to be passed on
398 // to Javascript. 394 // to Javascript.
399 static EventModifiers CocoaToEventRecordModifiers(NSUInteger inMods) { 395 EventModifiers CocoaToEventRecordModifiers(NSUInteger inMods) {
400 EventModifiers outMods = 0; 396 EventModifiers outMods = 0;
401 397
402 // NSEvent distinuishes between the shift key being down and the capslock key, 398 // NSEvent distinuishes between the shift key being down and the capslock key,
403 // but the W3C event spec does not make this distinction. 399 // but the W3C event spec does not make this distinction.
404 if (inMods & (NSAlphaShiftKeyMask | NSShiftKeyMask)) 400 if (inMods & (NSAlphaShiftKeyMask | NSShiftKeyMask))
405 outMods |= shiftKey; 401 outMods |= shiftKey;
406 if (inMods & NSControlKeyMask) 402 if (inMods & NSControlKeyMask)
407 outMods |= controlKey; 403 outMods |= controlKey;
408 if (inMods & NSAlternateKeyMask) 404 if (inMods & NSAlternateKeyMask)
409 outMods |= optionKey; 405 outMods |= optionKey;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 nsPluginEventType_GetFocusEvent = (osEvt + 16), 496 nsPluginEventType_GetFocusEvent = (osEvt + 16),
501 nsPluginEventType_LoseFocusEvent, 497 nsPluginEventType_LoseFocusEvent,
502 nsPluginEventType_AdjustCursorEvent, 498 nsPluginEventType_AdjustCursorEvent,
503 nsPluginEventType_MenuCommandEvent, 499 nsPluginEventType_MenuCommandEvent,
504 nsPluginEventType_ClippingChangedEvent, 500 nsPluginEventType_ClippingChangedEvent,
505 nsPluginEventType_ScrollingBeginsEvent, 501 nsPluginEventType_ScrollingBeginsEvent,
506 nsPluginEventType_ScrollingEndsEvent, 502 nsPluginEventType_ScrollingEndsEvent,
507 nsPluginEventType_Idle = 0 503 nsPluginEventType_Idle = 0
508 }; 504 };
509 505
506 NPError InitializePlugin() {
507 #if !defined(O3D_INTERNAL_PLUGIN)
508 if (!o3d::SetupOutOfMemoryHandler())
509 return NPERR_MODULE_LOAD_FAILED_ERROR;
510
511 o3d::InitializeBreakpad();
512
513 #ifdef CFTIMER
514 o3d::gRenderTimer.Start();
515 #endif // CFTIMER
516
517 // Initialize the AtExitManager so that base singletons can be
518 // destroyed properly.
519 g_at_exit_manager.reset(new base::AtExitManager());
520
521 // Turn on the logging.
522 CommandLine::Init(0, NULL);
523 InitLogging("debug.log",
524 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
525 logging::DONT_LOCK_LOG_FILE,
526 logging::APPEND_TO_OLD_LOG_FILE);
527
528 DLOG(INFO) << "NP_Initialize";
529
530 o3d::SetupOutOfMemoryHandler();
531 #endif // O3D_INTERNAL_PLUGIN
532
533 return NPERR_NO_ERROR;
534 }
535
536 // Negotiates the best plugin event model, sets the browser to use that,
537 // and updates the PluginObject so we can remember which one we chose.
538 // We favor the newer Cocoa-based model, but can cope with browsers that
539 // only support the original event model, or indeed can't even understand
540 // what we are asking for.
541 // However, right at the minute, we shun the Cocoa event model because its
542 // NPP_SetWindow messages don't contain a WindowRef or NSWindow so we would
543 // not get enough info to create our AGL context. We'll go back to
544 // preferring Cocoa once we have worked out how to deal with that.
545 // Cannot actually fail -
546 void Mac_SetBestEventModel(NPP instance, PluginObject* obj) {
547 NPError err = NPERR_NO_ERROR;
548 NPEventModel event_model = NPEventModelCarbon;
549 NPBool supportsCocoaEventModel = FALSE;
550 NPBool supportsCarbonEventModel = FALSE;
551
552 // See if browser supports Cocoa event model.
553 err = NPN_GetValue(instance,
554 NPNVsupportsCocoaBool,
555 &supportsCocoaEventModel);
556 if (err != NPERR_NO_ERROR) {
557 supportsCocoaEventModel = FALSE;
558 err = NPERR_NO_ERROR; // browser doesn't support switchable event models
559 }
560
561 // See if browser supports Carbon event model.
562 err = NPN_GetValue(instance,
563 NPNVsupportsCarbonBool,
564 &supportsCarbonEventModel);
565 if (err != NPERR_NO_ERROR) {
566 supportsCarbonEventModel = FALSE;
567 err = NPERR_NO_ERROR;
568 }
569
570 // Now we've collected our data, the decision phase begins.
571
572 // If we didn't successfully get TRUE for either question, the browser
573 // just does not know about the new switchable event models, so must only
574 // support the old Carbon event model.
575 if (!(supportsCocoaEventModel || supportsCarbonEventModel)) {
576 supportsCarbonEventModel = TRUE;
577 obj->event_model_ = NPEventModelCarbon;
578 }
579
580 // Default to Carbon event model, because the new version of the
581 // Cocoa event model spec does not supply sufficient window
582 // information in its Cocoa NPP_SetWindow calls for us to bind an
583 // AGL context to the browser window.
584 NPEventModel model_to_use =
585 (supportsCarbonEventModel) ? NPEventModelCarbon : NPEventModelCocoa;
586 NPN_SetValue(instance, NPPVpluginEventModel,
587 reinterpret_cast<void*>(model_to_use));
588 obj->event_model_ = model_to_use;
589 }
590
591
592 // Negotiates the best plugin drawing model, sets the browser to use that,
593 // and updates the PluginObject so we can remember which one we chose.
594 // Returns NPERR_NO_ERROR (0) if successful, otherwise an NPError code.
595 NPError Mac_SetBestDrawingModel(NPP instance, PluginObject* obj) {
596 NPError err = NPERR_NO_ERROR;
597 NPBool supportsCoreGraphics = FALSE;
598 NPBool supportsOpenGL = FALSE;
599 NPBool supportsQuickDraw = FALSE;
600 NPDrawingModel drawing_model = NPDrawingModelQuickDraw;
601
602 // test for direct OpenGL support
603 err = NPN_GetValue(instance,
604 NPNVsupportsOpenGLBool,
605 &supportsOpenGL);
606 if (err != NPERR_NO_ERROR)
607 supportsOpenGL = FALSE;
608
609 // test for QuickDraw support
610 err = NPN_GetValue(instance,
611 NPNVsupportsQuickDrawBool,
612 &supportsQuickDraw);
613 if (err != NPERR_NO_ERROR)
614 supportsQuickDraw = FALSE;
615
616 // Test for Core Graphics support
617 err = NPN_GetValue(instance,
618 NPNVsupportsCoreGraphicsBool,
619 &supportsCoreGraphics);
620 if (err != NPERR_NO_ERROR)
621 supportsCoreGraphics = FALSE;
622
623
624 // In order of preference. Preference is now determined by compatibility,
625 // not by modernity, and so is the opposite of the order I first used.
626 if (supportsQuickDraw && !(obj->event_model_ == NPEventModelCocoa)) {
627 drawing_model = NPDrawingModelQuickDraw;
628 } else if (supportsCoreGraphics) {
629 drawing_model = NPDrawingModelCoreGraphics;
630 } else if (supportsOpenGL) {
631 drawing_model = NPDrawingModelOpenGL;
632 } else {
633 // This case is for browsers that didn't even understand the question
634 // eg FF2, so drawing models are not supported, just assume QuickDraw.
635 obj->drawing_model_ = NPDrawingModelQuickDraw;
636 return NPERR_NO_ERROR;
637 }
638
639 err = NPN_SetValue(instance, NPPVpluginDrawingModel,
640 reinterpret_cast<void*>(drawing_model));
641 if (err != NPERR_NO_ERROR)
642 return err;
643
644 obj->drawing_model_ = drawing_model;
645
646 return NPERR_NO_ERROR;
647 }
648 } // end anonymous namespace
649
650 #if defined(O3D_INTERNAL_PLUGIN)
651 namespace o3d {
652 #else
653 extern "C" {
654 #endif
655
656 NPError OSCALL NP_Initialize(NPNetscapeFuncs* browserFuncs) {
657 HANDLE_CRASHES;
658 NPError retval = InitializeNPNApi(browserFuncs);
659 if (retval != NPERR_NO_ERROR) return retval;
660 return InitializePlugin();
661 }
662
663 #if !defined(O3D_INTERNAL_PLUGIN)
664
665 // Wrapper that discards the return value to match the expected type of
666 // NPP_ShutdownUPP.
667 void NPP_ShutdownWrapper() {
668 NP_Shutdown();
669 }
670
671 // This code is needed to support browsers based on a slightly dated version
672 // of the NPAPI such as Firefox 2, and Camino 1.6. These browsers expect there
673 // to be a main() to call to do basic setup.
674 int main(NPNetscapeFuncs* browserFuncs,
675 NPPluginFuncs* pluginFuncs,
676 NPP_ShutdownUPP* shutdownProc) {
677 HANDLE_CRASHES;
678 NPError error = NP_Initialize(browserFuncs);
679 if (error == NPERR_NO_ERROR)
680 error = NP_GetEntryPoints(pluginFuncs);
681 *shutdownProc = NPP_ShutdownWrapper;
682
683 return error;
684 }
685
686 #endif // O3D_INTERNAL_PLUGIN
687
688 NPError OSCALL NP_Shutdown(void) {
689 #if !defined(O3D_INTERNAL_PLUGIN)
690 HANDLE_CRASHES;
691 DLOG(INFO) << "NP_Shutdown";
692
693 if (g_logger) {
694 // Do a last sweep to aggregate metrics before we shut down
695 g_logger->ProcessMetrics(true, false);
696 delete g_logger;
697 g_logger = NULL;
698 g_logging_initialized = false;
699 stats_report::g_global_metrics.Uninitialize();
700 }
701
702 CommandLine::Terminate();
703
704 #ifdef CFTIMER
705 o3d::gRenderTimer.Stop();
706 #endif
707
708 // Force all base singletons to be destroyed.
709 g_at_exit_manager.reset(NULL);
710
711 o3d::ShutdownBreakpad();
712 #endif // O3D_INTERNAL_PLUGIN
713
714 return NPERR_NO_ERROR;
715 }
716
717 } // namespace o3d / extern "C"
718
719
720 namespace o3d {
721
722 NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) {
723 return NPERR_INVALID_PARAM;
724 }
510 725
511 bool HandleMacEvent(EventRecord* the_event, NPP instance) { 726 bool HandleMacEvent(EventRecord* the_event, NPP instance) {
512 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 727 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
513 bool handled = false; 728 bool handled = false;
514 WindowRef fullscreen_window = obj->GetFullscreenMacWindow(); 729 WindowRef fullscreen_window = obj->GetFullscreenMacWindow();
515 730
516 if (g_logger) g_logger->UpdateLogging(); 731 if (g_logger) g_logger->UpdateLogging();
517 732
518 // Help the plugin keep track of when we last saw an event so the CFTimer can 733 // Help the plugin keep track of when we last saw an event so the CFTimer can
519 // notice if we get cut off, eg by our tab being hidden by Safari, which there 734 // notice if we get cut off, eg by our tab being hidden by Safari, which there
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 break; 802 break;
588 case nsPluginEventType_ScrollingEndsEvent: 803 case nsPluginEventType_ScrollingEndsEvent:
589 obj->SetScrollIsInProgress(false); 804 obj->SetScrollIsInProgress(false);
590 break; 805 break;
591 default: 806 default:
592 break; 807 break;
593 } 808 }
594 return handled; 809 return handled;
595 } 810 }
596 811
597 NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) { 812 void RenderOnDemandCallbackHandler::Run() {
598 return NPERR_INVALID_PARAM; 813 obj_->SetWantsRedraw(true);
599 } 814 }
600 815
601 extern "C" { 816 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
602 NPError InitializePlugin() { 817 char* argn[], char* argv[], NPSavedData* saved) {
603 if (!o3d::SetupOutOfMemoryHandler()) 818 HANDLE_CRASHES;
604 return NPERR_MODULE_LOAD_FAILED_ERROR;
605 819
606 InitializeBreakpad(); 820 NPError err = NPERR_NO_ERROR;
607 821
vangelis 2009/07/09 02:14:11 g_logging_initialized won't be defined if defined(
608 #ifdef CFTIMER 822 if (!g_logging_initialized) {
609 gRenderTimer.Start(); 823 GetUserAgentMetrics(instance);
610 #endif // CFTIMER 824 GetUserConfigMetrics();
611 825 // Create usage stats logs object
612 // Initialize the AtExitManager so that base singletons can be 826 g_logger = o3d::PluginLogging::InitializeUsageStatsLogging();
613 // destroyed properly. 827 g_logging_initialized = true;
614 g_at_exit_manager.reset(new base::AtExitManager());
615
616 // Turn on the logging.
617 CommandLine::Init(0, NULL);
618 InitLogging("debug.log",
619 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
620 logging::DONT_LOCK_LOG_FILE,
621 logging::APPEND_TO_OLD_LOG_FILE);
622
623 DLOG(INFO) << "NP_Initialize";
624
625 o3d::SetupOutOfMemoryHandler();
626
627 return NPERR_NO_ERROR;
628 } 828 }
629 829
630 NPError OSCALL NP_Initialize(NPNetscapeFuncs* browserFuncs) { 830 PluginObject* pluginObject = glue::_o3d::PluginObject::Create(
631 HANDLE_CRASHES; 831 instance);
632 NPError retval = InitializeNPNApi(browserFuncs); 832 instance->pdata = pluginObject;
633 if (retval != NPERR_NO_ERROR) return retval; 833 glue::_o3d::InitializeGlue(instance);
634 return InitializePlugin(); 834 pluginObject->Init(argc, argn, argv);
835
836 Mac_SetBestEventModel(instance,
837 static_cast<PluginObject*>(instance->pdata));
838
839 err = Mac_SetBestDrawingModel(
840 instance, static_cast<PluginObject*>(instance->pdata));
841 if (err != NPERR_NO_ERROR)
842 return err;
843 return NPERR_NO_ERROR;
844 }
845
846 NPError NPP_Destroy(NPP instance, NPSavedData** save) {
847 HANDLE_CRASHES;
848 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
849 if (obj) {
850 #if defined(CFTIMER)
851 o3d::gRenderTimer.RemoveInstance(instance);
852 #endif
853
854 obj->TearDown();
855 NPN_ReleaseObject(obj);
856 instance->pdata = NULL;
635 } 857 }
636 858
637 // Wrapper that discards the return value to match the expected type of 859 return NPERR_NO_ERROR;
638 // NPP_ShutdownUPP. 860 }
639 void NPP_ShutdownWrapper() { 861
640 NP_Shutdown(); 862 bool CheckForAGLError() {
863 return aglGetError() != AGL_NO_ERROR;
864 }
865
866
867 NPError NPP_SetWindow(NPP instance, NPWindow* window) {
868 HANDLE_CRASHES;
869 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
870 WindowRef new_window = NULL;
871
872 assert(window != NULL);
873
874 if (window->window == NULL)
875 return NPERR_NO_ERROR;
876
877 obj->last_plugin_loc_.h = window->x;
878 obj->last_plugin_loc_.v = window->y;
879
880 switch (obj->drawing_model_) {
881 case NPDrawingModelOpenGL: {
882 NP_GLContext* np_gl = reinterpret_cast<NP_GLContext*>(window->window);
883 if (obj->event_model_ == NPEventModelCocoa) {
884 NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_gl->window);
885 new_window = reinterpret_cast<WindowRef>([ns_window windowRef]);
886 } else {
887 new_window = np_gl->window;
888 }
889 obj->mac_2d_context_ = NULL;
890 obj->mac_cgl_context_ = np_gl->context;
891 break;
892 }
893 case NPDrawingModelCoreGraphics: {
894 // Safari 4 sets window->window to NULL when in Cocoa event mode.
895 if (window->window != NULL) {
896 NP_CGContext* np_cg = reinterpret_cast<NP_CGContext*>(window->window);
897 if (obj->event_model_ == NPEventModelCocoa) {
898 NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_cg->window);
899 new_window = reinterpret_cast<WindowRef>([ns_window windowRef]);
900 } else {
901 new_window = np_cg->window;
902 }
903 obj->mac_2d_context_ = np_cg->context;
904 }
905 break;
906 }
907 case NPDrawingModelQuickDraw: {
908 NP_Port* np_qd = reinterpret_cast<NP_Port*>(window->window);
909 obj->mac_2d_context_ = np_qd->port;
910 if (np_qd->port)
911 new_window = GetWindowFromPort(np_qd->port);
912 break;
913 }
914 default:
915 return NPERR_INCOMPATIBLE_VERSION_ERROR;
916 break;
641 } 917 }
642 918
643 // This code is needed to support browsers based on a slightly dated version 919 // Whether the target window has changed.
644 // of the NPAPI such as Firefox 2, and Camino 1.6. These browsers expect there 920 bool window_changed = new_window != obj->mac_window_;
645 // to be a main() to call to do basic setup.
646 int main(NPNetscapeFuncs* browserFuncs,
647 NPPluginFuncs* pluginFuncs,
648 NPP_ShutdownUPP* shutdownProc) {
649 HANDLE_CRASHES;
650 NPError error = NP_Initialize(browserFuncs);
651 if (error == NPERR_NO_ERROR)
652 error = NP_GetEntryPoints(pluginFuncs);
653 *shutdownProc = NPP_ShutdownWrapper;
654 921
655 return error; 922 // Whether we already had a window before this call.
656 } 923 bool had_a_window = obj->mac_window_ != NULL;
657 924
658 NPError OSCALL NP_Shutdown(void) { 925 obj->mac_window_ = new_window;
659 HANDLE_CRASHES;
660 DLOG(INFO) << "NP_Shutdown";
661 926
662 if (g_logger) { 927 if (obj->drawing_model_ == NPDrawingModelOpenGL) {
663 // Do a last sweep to aggregate metrics before we shut down 928 CGLSetCurrentContext(obj->mac_cgl_context_);
664 g_logger->ProcessMetrics(true, false); 929 } else if (!had_a_window && obj->mac_agl_context_ == NULL) { // setup AGL con text
665 delete g_logger; 930 AGLPixelFormat myAGLPixelFormat = NULL;
666 g_logger = NULL;
667 g_logging_initialized = false;
668 stats_report::g_global_metrics.Uninitialize();
669 }
670 931
671 CommandLine::Terminate(); 932 // We need to spec out a few similar but different sets of renderer
672 933 // specifications - define some macros to lessen the duplication.
673 #ifdef CFTIMER
674 gRenderTimer.Stop();
675 #endif
676
677 // Force all base singletons to be destroyed.
678 g_at_exit_manager.reset(NULL);
679
680 ShutdownBreakpad();
681
682 return NPERR_NO_ERROR;
683 }
684
685 // Negotiates the best plugin event model, sets the browser to use that,
686 // and updates the PluginObject so we can remember which one we chose.
687 // We favor the newer Cocoa-based model, but can cope with browsers that
688 // only support the original event model, or indeed can't even understand
689 // what we are asking for.
690 // However, right at the minute, we shun the Cocoa event model because its
691 // NPP_SetWindow messages don't contain a WindowRef or NSWindow so we would
692 // not get enough info to create our AGL context. We'll go back to
693 // preferring Cocoa once we have worked out how to deal with that.
694 // Cannot actually fail -
695 static void Mac_SetBestEventModel(NPP instance, PluginObject* obj) {
696 NPError err = NPERR_NO_ERROR;
697 NPEventModel event_model = NPEventModelCarbon;
698 NPBool supportsCocoaEventModel = FALSE;
699 NPBool supportsCarbonEventModel = FALSE;
700
701 // See if browser supports Cocoa event model.
702 err = NPN_GetValue(instance,
703 NPNVsupportsCocoaBool,
704 &supportsCocoaEventModel);
705 if (err != NPERR_NO_ERROR) {
706 supportsCocoaEventModel = FALSE;
707 err = NPERR_NO_ERROR; // browser doesn't support switchable event models
708 }
709
710 // See if browser supports Carbon event model.
711 err = NPN_GetValue(instance,
712 NPNVsupportsCarbonBool,
713 &supportsCarbonEventModel);
714 if (err != NPERR_NO_ERROR) {
715 supportsCarbonEventModel = FALSE;
716 err = NPERR_NO_ERROR;
717 }
718
719 // Now we've collected our data, the decision phase begins.
720
721 // If we didn't successfully get TRUE for either question, the browser
722 // just does not know about the new switchable event models, so must only
723 // support the old Carbon event model.
724 if (!(supportsCocoaEventModel || supportsCarbonEventModel)) {
725 supportsCarbonEventModel = TRUE;
726 obj->event_model_ = NPEventModelCarbon;
727 }
728
729 // Default to Carbon event model, because the new version of the
730 // Cocoa event model spec does not supply sufficient window
731 // information in its Cocoa NPP_SetWindow calls for us to bind an
732 // AGL context to the browser window.
733 NPEventModel model_to_use =
734 (supportsCarbonEventModel) ? NPEventModelCarbon : NPEventModelCocoa;
735 NPN_SetValue(instance, NPPVpluginEventModel,
736 reinterpret_cast<void*>(model_to_use));
737 obj->event_model_ = model_to_use;
738 }
739
740
741 // Negotiates the best plugin drawing model, sets the browser to use that,
742 // and updates the PluginObject so we can remember which one we chose.
743 // Returns NPERR_NO_ERROR (0) if successful, otherwise an NPError code.
744 static NPError Mac_SetBestDrawingModel(NPP instance, PluginObject* obj) {
745 NPError err = NPERR_NO_ERROR;
746 NPBool supportsCoreGraphics = FALSE;
747 NPBool supportsOpenGL = FALSE;
748 NPBool supportsQuickDraw = FALSE;
749 NPDrawingModel drawing_model = NPDrawingModelQuickDraw;
750
751 // test for direct OpenGL support
752 err = NPN_GetValue(instance,
753 NPNVsupportsOpenGLBool,
754 &supportsOpenGL);
755 if (err != NPERR_NO_ERROR)
756 supportsOpenGL = FALSE;
757
758 // test for QuickDraw support
759 err = NPN_GetValue(instance,
760 NPNVsupportsQuickDrawBool,
761 &supportsQuickDraw);
762 if (err != NPERR_NO_ERROR)
763 supportsQuickDraw = FALSE;
764
765 // Test for Core Graphics support
766 err = NPN_GetValue(instance,
767 NPNVsupportsCoreGraphicsBool,
768 &supportsCoreGraphics);
769 if (err != NPERR_NO_ERROR)
770 supportsCoreGraphics = FALSE;
771
772
773 // In order of preference. Preference is now determined by compatibility,
774 // not by modernity, and so is the opposite of the order I first used.
775 if (supportsQuickDraw && !(obj->event_model_ == NPEventModelCocoa)) {
776 drawing_model = NPDrawingModelQuickDraw;
777 } else if (supportsCoreGraphics) {
778 drawing_model = NPDrawingModelCoreGraphics;
779 } else if (supportsOpenGL) {
780 drawing_model = NPDrawingModelOpenGL;
781 } else {
782 // This case is for browsers that didn't even understand the question
783 // eg FF2, so drawing models are not supported, just assume QuickDraw.
784 obj->drawing_model_ = NPDrawingModelQuickDraw;
785 return NPERR_NO_ERROR;
786 }
787
788 err = NPN_SetValue(instance, NPPVpluginDrawingModel,
789 reinterpret_cast<void*>(drawing_model));
790 if (err != NPERR_NO_ERROR)
791 return err;
792
793 obj->drawing_model_ = drawing_model;
794
795 return NPERR_NO_ERROR;
796 }
797
798
799 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
800 char* argn[], char* argv[], NPSavedData* saved) {
801 HANDLE_CRASHES;
802
803 NPError err = NPERR_NO_ERROR;
804
805 if (!g_logging_initialized) {
806 GetUserAgentMetrics(instance);
807 GetUserConfigMetrics();
808 // Create usage stats logs object
809 g_logger = o3d::PluginLogging::InitializeUsageStatsLogging();
810 g_logging_initialized = true;
811 }
812
813 PluginObject* pluginObject = glue::_o3d::PluginObject::Create(
814 instance);
815 instance->pdata = pluginObject;
816 glue::_o3d::InitializeGlue(instance);
817 pluginObject->Init(argc, argn, argv);
818
819 Mac_SetBestEventModel(instance,
820 static_cast<PluginObject*>(instance->pdata));
821
822 err = Mac_SetBestDrawingModel(
823 instance, static_cast<PluginObject*>(instance->pdata));
824 if (err != NPERR_NO_ERROR)
825 return err;
826 return NPERR_NO_ERROR;
827 }
828
829 NPError NPP_Destroy(NPP instance, NPSavedData** save) {
830 HANDLE_CRASHES;
831 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
832 if (obj) {
833 #if defined(CFTIMER)
834 gRenderTimer.RemoveInstance(instance);
835 #endif
836
837 obj->TearDown();
838 NPN_ReleaseObject(obj);
839 instance->pdata = NULL;
840 }
841
842 return NPERR_NO_ERROR;
843 }
844
845 static bool CheckForAGLError() {
846 return aglGetError() != AGL_NO_ERROR;
847 }
848
849
850 NPError NPP_SetWindow(NPP instance, NPWindow* window) {
851 HANDLE_CRASHES;
852 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
853 WindowRef new_window = NULL;
854
855 assert(window != NULL);
856
857 if (window->window == NULL)
858 return NPERR_NO_ERROR;
859
860 obj->last_plugin_loc_.h = window->x;
861 obj->last_plugin_loc_.v = window->y;
862
863 switch (obj->drawing_model_) {
864 case NPDrawingModelOpenGL: {
865 NP_GLContext* np_gl = reinterpret_cast<NP_GLContext*>(window->window);
866 if (obj->event_model_ == NPEventModelCocoa) {
867 NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_gl->window);
868 new_window = reinterpret_cast<WindowRef>([ns_window windowRef]);
869 } else {
870 new_window = np_gl->window;
871 }
872 obj->mac_2d_context_ = NULL;
873 obj->mac_cgl_context_ = np_gl->context;
874 break;
875 }
876 case NPDrawingModelCoreGraphics: {
877 // Safari 4 sets window->window to NULL when in Cocoa event mode.
878 if (window->window != NULL) {
879 NP_CGContext* np_cg = reinterpret_cast<NP_CGContext*>(window->window);
880 if (obj->event_model_ == NPEventModelCocoa) {
881 NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_cg->window);
882 new_window = reinterpret_cast<WindowRef>([ns_window windowRef]);
883 } else {
884 new_window = np_cg->window;
885 }
886 obj->mac_2d_context_ = np_cg->context;
887 }
888 break;
889 }
890 case NPDrawingModelQuickDraw: {
891 NP_Port* np_qd = reinterpret_cast<NP_Port*>(window->window);
892 obj->mac_2d_context_ = np_qd->port;
893 if (np_qd->port)
894 new_window = GetWindowFromPort(np_qd->port);
895 break;
896 }
897 default:
898 return NPERR_INCOMPATIBLE_VERSION_ERROR;
899 break;
900 }
901
902 // Whether the target window has changed.
903 bool window_changed = new_window != obj->mac_window_;
904
905 // Whether we already had a window before this call.
906 bool had_a_window = obj->mac_window_ != NULL;
907
908 obj->mac_window_ = new_window;
909
910 if (obj->drawing_model_ == NPDrawingModelOpenGL) {
911 CGLSetCurrentContext(obj->mac_cgl_context_);
912 } else if (!had_a_window && obj->mac_agl_context_ == NULL) { // setup AGL c ontext
913 AGLPixelFormat myAGLPixelFormat = NULL;
914
915 // We need to spec out a few similar but different sets of renderer
916 // specifications - define some macros to lessen the duplication.
917 #define O3D_DEPTH_SETTINGS AGL_RGBA, AGL_DEPTH_SIZE, 24, 934 #define O3D_DEPTH_SETTINGS AGL_RGBA, AGL_DEPTH_SIZE, 24,
918 #define O3D_STENCIL_SETTINGS AGL_STENCIL_SIZE, 8, 935 #define O3D_STENCIL_SETTINGS AGL_STENCIL_SIZE, 8,
919 #define O3D_HARDWARE_RENDERER AGL_ACCELERATED, AGL_NO_RECOVERY, 936 #define O3D_HARDWARE_RENDERER AGL_ACCELERATED, AGL_NO_RECOVERY,
920 #define O3D_SOFTWARE_RENDERER AGL_RENDERER_ID, AGL_RENDERER_GENERIC_FLOAT_ID, 937 #define O3D_SOFTWARE_RENDERER AGL_RENDERER_ID, AGL_RENDERER_GENERIC_FLOAT_ID,
921 #define O3D_MULTISAMPLE AGL_MULTISAMPLE, \ 938 #define O3D_MULTISAMPLE AGL_MULTISAMPLE, \
922 AGL_SAMPLE_BUFFERS_ARB, 1, AGL_SAMPLES_ARB, 4, AGL_MULTISAMPLE, 939 AGL_SAMPLE_BUFFERS_ARB, 1, AGL_SAMPLES_ARB, 4, AGL_MULTISAMPLE,
923 #define O3D_END AGL_NONE 940 #define O3D_END AGL_NONE
924 941
925 #ifdef USE_AGL_DOUBLE_BUFFER 942 #ifdef USE_AGL_DOUBLE_BUFFER
926 #define O3D_DOUBLE_BUFFER_SETTINGS AGL_DOUBLEBUFFER, 943 #define O3D_DOUBLE_BUFFER_SETTINGS AGL_DOUBLEBUFFER,
927 #else 944 #else
928 #define O3D_DOUBLE_BUFFER_SETTINGS 945 #define O3D_DOUBLE_BUFFER_SETTINGS
929 #endif 946 #endif
930 947
931 if (!UseSoftwareRenderer()) { 948 if (!UseSoftwareRenderer()) {
932 // Try to create a hardware context with the following 949 // Try to create a hardware context with the following
933 // specification 950 // specification
934 GLint attributes[] = { 951 GLint attributes[] = {
952 O3D_DEPTH_SETTINGS
953 O3D_STENCIL_SETTINGS
954 O3D_DOUBLE_BUFFER_SETTINGS
955 O3D_HARDWARE_RENDERER
956 O3D_MULTISAMPLE
957 O3D_END
958 };
959 myAGLPixelFormat = aglChoosePixelFormat(NULL,
960 0,
961 attributes);
962
963 // If this fails, then don't try to be as ambitious
964 // (so don't ask for multi-sampling), but still require hardware
965 if (myAGLPixelFormat == NULL) {
966 GLint low_end_attributes[] = {
935 O3D_DEPTH_SETTINGS 967 O3D_DEPTH_SETTINGS
936 O3D_STENCIL_SETTINGS 968 O3D_STENCIL_SETTINGS
937 O3D_DOUBLE_BUFFER_SETTINGS 969 O3D_DOUBLE_BUFFER_SETTINGS
938 O3D_HARDWARE_RENDERER 970 O3D_HARDWARE_RENDERER
939 O3D_MULTISAMPLE
940 O3D_END 971 O3D_END
941 }; 972 };
942 myAGLPixelFormat = aglChoosePixelFormat(NULL, 973 myAGLPixelFormat = aglChoosePixelFormat(NULL,
943 0, 974 0,
944 attributes); 975 low_end_attributes);
945
946 // If this fails, then don't try to be as ambitious
947 // (so don't ask for multi-sampling), but still require hardware
948 if (myAGLPixelFormat == NULL) {
949 GLint low_end_attributes[] = {
950 O3D_DEPTH_SETTINGS
951 O3D_STENCIL_SETTINGS
952 O3D_DOUBLE_BUFFER_SETTINGS
953 O3D_HARDWARE_RENDERER
954 O3D_END
955 };
956 myAGLPixelFormat = aglChoosePixelFormat(NULL,
957 0,
958 low_end_attributes);
959 }
960 } 976 }
961 977 }
962 if (myAGLPixelFormat == NULL) { 978
963 // Fallback to software renderer either if the vendorID/gpuID 979 if (myAGLPixelFormat == NULL) {
964 // is known to be problematic, or if the hardware context failed 980 // Fallback to software renderer either if the vendorID/gpuID
965 // to get created 981 // is known to be problematic, or if the hardware context failed
966 // 982 // to get created
967 // Note that we don't request multisampling since it's too slow. 983 //
968 GLint software_renderer_attributes[] = { 984 // Note that we don't request multisampling since it's too slow.
969 O3D_DEPTH_SETTINGS 985 GLint software_renderer_attributes[] = {
970 O3D_STENCIL_SETTINGS 986 O3D_DEPTH_SETTINGS
971 O3D_DOUBLE_BUFFER_SETTINGS 987 O3D_STENCIL_SETTINGS
972 O3D_SOFTWARE_RENDERER 988 O3D_DOUBLE_BUFFER_SETTINGS
973 O3D_END 989 O3D_SOFTWARE_RENDERER
974 }; 990 O3D_END
975 myAGLPixelFormat = aglChoosePixelFormat(NULL, 991 };
976 0, 992 myAGLPixelFormat = aglChoosePixelFormat(NULL,
977 software_renderer_attributes); 993 0,
978 994 software_renderer_attributes);
979 obj->SetRendererIsSoftware(true); 995
980 } 996 obj->SetRendererIsSoftware(true);
981 997 }
982 if (myAGLPixelFormat == NULL || CheckForAGLError()) 998
983 return NPERR_MODULE_LOAD_FAILED_ERROR; 999 if (myAGLPixelFormat == NULL || CheckForAGLError())
984 1000 return NPERR_MODULE_LOAD_FAILED_ERROR;
985 obj->mac_agl_context_ = aglCreateContext(myAGLPixelFormat, NULL); 1001
986 1002 obj->mac_agl_context_ = aglCreateContext(myAGLPixelFormat, NULL);
987 if (CheckForAGLError()) 1003
988 return NPERR_MODULE_LOAD_FAILED_ERROR; 1004 if (CheckForAGLError())
989 1005 return NPERR_MODULE_LOAD_FAILED_ERROR;
990 aglDestroyPixelFormat(myAGLPixelFormat); 1006
991 1007 aglDestroyPixelFormat(myAGLPixelFormat);
992 if (!SetWindowForAGLContext(obj->mac_agl_context_, obj->mac_window_)) 1008
993 return NPERR_MODULE_LOAD_FAILED_ERROR; 1009 if (!SetWindowForAGLContext(obj->mac_agl_context_, obj->mac_window_))
994 1010 return NPERR_MODULE_LOAD_FAILED_ERROR;
995 aglSetCurrentContext(obj->mac_agl_context_); 1011
996 1012 aglSetCurrentContext(obj->mac_agl_context_);
997 GetOpenGLMetrics(); 1013
1014 GetOpenGLMetrics();
998 1015
999 #ifdef USE_AGL_DOUBLE_BUFFER 1016 #ifdef USE_AGL_DOUBLE_BUFFER
1000 GLint swapInterval = 1; // request synchronization 1017 GLint swapInterval = 1; // request synchronization
1001 aglSetInteger(obj->mac_agl_context_, AGL_SWAP_INTERVAL, &swapInterval); 1018 aglSetInteger(obj->mac_agl_context_, AGL_SWAP_INTERVAL, &swapInterval);
1002 #endif 1019 #endif
1003 } 1020 }
1004 1021
1005 int clipHeight = window->clipRect.bottom - window->clipRect.top; 1022 int clipHeight = window->clipRect.bottom - window->clipRect.top;
1006 int clipWidth = window->clipRect.right - window->clipRect.left; 1023 int clipWidth = window->clipRect.right - window->clipRect.left;
1007 1024
1008 int x_offset = window->clipRect.left - window->x; 1025 int x_offset = window->clipRect.left - window->x;
1009 int y_offset = window->clipRect.top - window->y; 1026 int y_offset = window->clipRect.top - window->y;
1010 int gl_x_origin = x_offset; 1027 int gl_x_origin = x_offset;
1011 int gl_y_origin = window->clipRect.bottom - (window->y + window->height); 1028 int gl_y_origin = window->clipRect.bottom - (window->y + window->height);
1012 1029
1013 // Firefox calls us with an empty cliprect all the time, toggling our 1030 // Firefox calls us with an empty cliprect all the time, toggling our
1014 // cliprect back and forth between empty and the normal value, particularly 1031 // cliprect back and forth between empty and the normal value, particularly
1015 // during scrolling. 1032 // during scrolling.
1016 // As we need to make our AGL surface track the clip rect, honoring all of 1033 // As we need to make our AGL surface track the clip rect, honoring all of
1017 // these calls would result in spectacular flashing. 1034 // these calls would result in spectacular flashing.
1018 // The goal here is to try to spot the calls we can safely ignore. 1035 // The goal here is to try to spot the calls we can safely ignore.
1019 // The bogus empty cliprects always have left and top of the real clip. 1036 // The bogus empty cliprects always have left and top of the real clip.
1020 // A null cliprect should always be honored ({0,0,0,0} means a hidden tab), 1037 // A null cliprect should always be honored ({0,0,0,0} means a hidden tab),
1021 // as should the first ever call to this function, 1038 // as should the first ever call to this function,
1022 // or an attempt to change the window. 1039 // or an attempt to change the window.
1023 // The call at the end of a scroll step is also honored. 1040 // The call at the end of a scroll step is also honored.
1024 // Otherwise, skip this change and do not hide our context. 1041 // Otherwise, skip this change and do not hide our context.
1025 bool is_empty_cliprect = (clipHeight <= 0 || clipWidth <= 0); 1042 bool is_empty_cliprect = (clipHeight <= 0 || clipWidth <= 0);
1026 bool is_null_cliprect = (window->clipRect.bottom == 0 && 1043 bool is_null_cliprect = (window->clipRect.bottom == 0 &&
1027 window->clipRect.top == 0 && 1044 window->clipRect.top == 0 &&
1028 window->clipRect.left == 0 && 1045 window->clipRect.left == 0 &&
1029 window->clipRect.right == 0); 1046 window->clipRect.right == 0);
1030 1047
1031 if (is_empty_cliprect && (!is_null_cliprect) && 1048 if (is_empty_cliprect && (!is_null_cliprect) &&
1032 had_a_window && (!window_changed) && !obj->ScrollIsInProgress()) { 1049 had_a_window && (!window_changed) && !obj->ScrollIsInProgress()) {
1050 return NPERR_NO_ERROR;
1051 }
1052
1053 // Workaround - the Apple software renderer crashes if you set the drawing
1054 // area to 0x0, so use 1x1.
1055 if (is_empty_cliprect && obj->RendererIsSoftware())
1056 clipWidth = clipHeight = 1;
1057
1058 // update size and location of the agl context
1059 if (obj->mac_agl_context_) {
1060
1061 // We already had a window, and now we've got a different window -
1062 // this can happen when the user drags out a tab in Safari into its own
1063 // window.
1064 if (had_a_window && window_changed)
1065 SetWindowForAGLContext(obj->mac_agl_context_, obj->mac_window_);
1066
1067 aglSetCurrentContext(obj->mac_agl_context_);
1068
1069 Rect windowRect = {0, 0, 0, 0};
1070 if (obj->drawing_model_ == NPDrawingModelQuickDraw)
1071 GetWindowBounds(obj->mac_window_, kWindowContentRgn, &windowRect);
1072 else
1073 GetWindowBounds(obj->mac_window_, kWindowStructureRgn, &windowRect);
1074
1075 int windowHeight = windowRect.bottom - windowRect.top;
1076
1077 // These are in window coords, the weird bit being that agl wants the
1078 // location of the bottom of the GL context in y flipped coords,
1079 // eg 100 would mean the bottom of the GL context was 100 up from the
1080 // bottom of the window.
1081 obj->last_buffer_rect_[0] = window->x + x_offset;
1082 obj->last_buffer_rect_[1] = (windowHeight - (window->y + clipHeight))
1083 - y_offset; // this param is y flipped
1084 obj->last_buffer_rect_[2] = clipWidth;
1085 obj->last_buffer_rect_[3] = clipHeight;
1086 obj->mac_surface_hidden_ = false;
1087
1088 // If in fullscreen, just remember the desired change in geometry so
1089 // we restore to the right rectangle.
1090 if (obj->GetFullscreenMacWindow() != NULL)
1033 return NPERR_NO_ERROR; 1091 return NPERR_NO_ERROR;
1034 } 1092
1035 1093 aglSetInteger(obj->mac_agl_context_, AGL_BUFFER_RECT,
1036 // Workaround - the Apple software renderer crashes if you set the drawing 1094 obj->last_buffer_rect_);
1037 // area to 0x0, so use 1x1. 1095 aglEnable(obj->mac_agl_context_, AGL_BUFFER_RECT);
1038 if (is_empty_cliprect && obj->RendererIsSoftware()) 1096 }
1039 clipWidth = clipHeight = 1; 1097
1040 1098 // Renderer is already initialized from a previous call to this function,
1041 // update size and location of the agl context 1099 // just update size and position and return.
1042 if (obj->mac_agl_context_) { 1100 if (had_a_window) {
1043
1044 // We already had a window, and now we've got a different window -
1045 // this can happen when the user drags out a tab in Safari into its own
1046 // window.
1047 if (had_a_window && window_changed)
1048 SetWindowForAGLContext(obj->mac_agl_context_, obj->mac_window_);
1049
1050 aglSetCurrentContext(obj->mac_agl_context_);
1051
1052 Rect windowRect = {0, 0, 0, 0};
1053 if (obj->drawing_model_ == NPDrawingModelQuickDraw)
1054 GetWindowBounds(obj->mac_window_, kWindowContentRgn, &windowRect);
1055 else
1056 GetWindowBounds(obj->mac_window_, kWindowStructureRgn, &windowRect);
1057
1058 int windowHeight = windowRect.bottom - windowRect.top;
1059
1060 // These are in window coords, the weird bit being that agl wants the
1061 // location of the bottom of the GL context in y flipped coords,
1062 // eg 100 would mean the bottom of the GL context was 100 up from the
1063 // bottom of the window.
1064 obj->last_buffer_rect_[0] = window->x + x_offset;
1065 obj->last_buffer_rect_[1] = (windowHeight - (window->y + clipHeight))
1066 - y_offset; // this param is y flipped
1067 obj->last_buffer_rect_[2] = clipWidth;
1068 obj->last_buffer_rect_[3] = clipHeight;
1069 obj->mac_surface_hidden_ = false;
1070
1071 // If in fullscreen, just remember the desired change in geometry so
1072 // we restore to the right rectangle.
1073 if (obj->GetFullscreenMacWindow() != NULL)
1074 return NPERR_NO_ERROR;
1075
1076 aglSetInteger(obj->mac_agl_context_, AGL_BUFFER_RECT,
1077 obj->last_buffer_rect_);
1078 aglEnable(obj->mac_agl_context_, AGL_BUFFER_RECT);
1079 }
1080
1081 // Renderer is already initialized from a previous call to this function,
1082 // just update size and position and return.
1083 if (had_a_window) {
1084 if (obj->renderer()) {
1085 obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin);
1086 obj->Resize(window->width, window->height);
1087 }
1088 return NPERR_NO_ERROR;
1089 }
1090
1091 // Create and assign the graphics context.
1092 o3d::DisplayWindowMac default_display;
1093 default_display.set_agl_context(obj->mac_agl_context_);
1094 default_display.set_cgl_context(obj->mac_cgl_context_);
1095
1096 obj->CreateRenderer(default_display);
1097
1098 // if the renderer cannot be created (maybe the features are not supported)
1099 // then we can proceed no further
1100 if (!obj->renderer()) {
1101 if (obj->mac_agl_context_) {
1102 ::aglDestroyContext(obj->mac_agl_context_);
1103 obj->mac_agl_context_ = NULL;
1104 }
1105 }
1106
1107 obj->client()->Init();
1108 obj->client()->SetRenderOnDemandCallback(
1109 new RenderOnDemandCallbackHandler(obj));
1110
1111 if (obj->renderer()) { 1101 if (obj->renderer()) {
1112 obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin); 1102 obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin);
1113 obj->Resize(window->width, window->height); 1103 obj->Resize(window->width, window->height);
1104 }
1105 return NPERR_NO_ERROR;
1106 }
1107
1108 // Create and assign the graphics context.
1109 o3d::DisplayWindowMac default_display;
1110 default_display.set_agl_context(obj->mac_agl_context_);
1111 default_display.set_cgl_context(obj->mac_cgl_context_);
1112
1113 obj->CreateRenderer(default_display);
1114
1115 // if the renderer cannot be created (maybe the features are not supported)
1116 // then we can proceed no further
1117 if (!obj->renderer()) {
1118 if (obj->mac_agl_context_) {
1119 ::aglDestroyContext(obj->mac_agl_context_);
1120 obj->mac_agl_context_ = NULL;
1121 }
1122 }
1123
1124 obj->client()->Init();
1125 obj->client()->SetRenderOnDemandCallback(
1126 new RenderOnDemandCallbackHandler(obj));
1127
1128 if (obj->renderer()) {
1129 obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin);
1130 obj->Resize(window->width, window->height);
1114 1131
1115 #ifdef CFTIMER 1132 #ifdef CFTIMER
1116 // now that the grahics context is setup, add this instance to the timer 1133 // now that the grahics context is setup, add this instance to the timer
1117 // list so it gets drawn repeatedly 1134 // list so it gets drawn repeatedly
1118 gRenderTimer.AddInstance(instance); 1135 gRenderTimer.AddInstance(instance);
1119 #endif // CFTIMER 1136 #endif // CFTIMER
1120 } 1137 }
1121 1138
1122 return NPERR_NO_ERROR; 1139 return NPERR_NO_ERROR;
1123 } 1140 }
1124 1141
1125 // Called when the browser has finished attempting to stream data to 1142 // Called when the browser has finished attempting to stream data to
1126 // a file as requested. If fname == NULL the attempt was not successful. 1143 // a file as requested. If fname == NULL the attempt was not successful.
1127 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { 1144 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
1128 HANDLE_CRASHES; 1145 HANDLE_CRASHES;
1129 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 1146 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
1130 StreamManager* stream_manager = obj->stream_manager(); 1147 StreamManager* stream_manager = obj->stream_manager();
1131 1148
1132 // Some browsers give us an absolute HFS path in fname, some give us an 1149 // Some browsers give us an absolute HFS path in fname, some give us an
1133 // absolute Posix path, so convert to Posix if needed. 1150 // absolute Posix path, so convert to Posix if needed.
1134 if ((!fname) || (fname[0] == '/') || !fname[0]) { 1151 if ((!fname) || (fname[0] == '/') || !fname[0]) {
1135 stream_manager->SetStreamFile(stream, fname); 1152 stream_manager->SetStreamFile(stream, fname);
1136 } else { 1153 } else {
1137 const char* converted_fname = CreatePosixFilePathFromHFSFilePath(fname); 1154 const char* converted_fname = CreatePosixFilePathFromHFSFilePath(fname);
1138 if (converted_fname == NULL) 1155 if (converted_fname == NULL)
1139 return; // TODO should also log error if we ever get here 1156 return; // TODO should also log error if we ever get here
1140 stream_manager->SetStreamFile(stream, converted_fname); 1157 stream_manager->SetStreamFile(stream, converted_fname);
1141 delete converted_fname; 1158 delete converted_fname;
1142 } 1159 }
1143 } 1160 }
1144 1161
1145 int16 NPP_HandleEvent(NPP instance, void* event) { 1162 int16 NPP_HandleEvent(NPP instance, void* event) {
1146 HANDLE_CRASHES; 1163 HANDLE_CRASHES;
1147 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 1164 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
1148 if (obj->event_model_ == NPEventModelCarbon) { 1165 if (obj->event_model_ == NPEventModelCarbon) {
1149 EventRecord* theEvent = static_cast<EventRecord*>(event); 1166 EventRecord* theEvent = static_cast<EventRecord*>(event);
1150 return HandleMacEvent(theEvent, instance) ? 1 : 0; 1167 return HandleMacEvent(theEvent, instance) ? 1 : 0;
1151 } else if (obj->event_model_ == NPEventModelCocoa){ 1168 } else if (obj->event_model_ == NPEventModelCocoa){
1152 return HandleCocoaEvent(instance, (NPCocoaEvent*)event) ? 1 : 0; 1169 return HandleCocoaEvent(instance, (NPCocoaEvent*)event) ? 1 : 0;
1153 } 1170 }
1154 return 0; 1171 return 0;
1155 } 1172 }
1156 }; // end extern "C" 1173
1174 } // namespace o3d
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698