// Go down shadow layer tree and apply transformations for scrollable layers. static void TransformShadowTree(nsDisplayListBuilder* aBuilder, nsFrameLoader* aFrameLoader, nsIFrame* aFrame, Layer* aLayer, const ViewTransform& aTransform) { ShadowLayer* shadow = aLayer->AsShadowLayer(); shadow->SetShadowClipRect(aLayer->GetClipRect()); shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion()); const FrameMetrics* metrics = GetFrameMetrics(aLayer); gfx3DMatrix shadowTransform; ViewTransform layerTransform = aTransform; if (metrics && metrics->IsScrollable()) { const ViewID scrollId = metrics->mScrollId; const nsContentView* view = aFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId); NS_ABORT_IF_FALSE(view, "Array of views should be consistent with layer tree"); const gfx3DMatrix& currentTransform = aLayer->GetTransform(); ViewTransform viewTransform = ComputeShadowTreeTransform( aFrame, aFrameLoader, metrics, view->GetViewConfig(), 1 / (GetXScale(currentTransform)*layerTransform.mXScale), 1 / (GetYScale(currentTransform)*layerTransform.mYScale) ); // Apply the layer's own transform *before* the view transform shadowTransform = gfx3DMatrix(viewTransform) * currentTransform; if (metrics->IsRootScrollable()) { layerTransform.mTranslation = viewTransform.mTranslation; // Apply the root frame translation *before* we do the rest of the transforms. nsIntPoint rootFrameOffset = GetRootFrameOffset(aFrame, aBuilder); shadowTransform = shadowTransform * gfx3DMatrix::Translation(float(rootFrameOffset.x), float(rootFrameOffset.y), 0.0); layerTransform.mXScale *= GetXScale(currentTransform); layerTransform.mYScale *= GetYScale(currentTransform); } } else { shadowTransform = aLayer->GetTransform(); } if (aLayer->GetIsFixedPosition() && !aLayer->GetParent()->GetIsFixedPosition()) { ReverseTranslate(shadowTransform, layerTransform); const nsIntRect* clipRect = shadow->GetShadowClipRect(); if (clipRect) { nsIntRect transformedClipRect(*clipRect); transformedClipRect.MoveBy(shadowTransform._41, shadowTransform._42); shadow->SetShadowClipRect(&transformedClipRect); } } shadow->SetShadowTransform(shadowTransform); for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { TransformShadowTree(aBuilder, aFrameLoader, aFrame, child, layerTransform); } }
// Use shadow layer tree to build display list for the browser's frame. static void BuildListForLayer(Layer* aLayer, nsFrameLoader* aRootFrameLoader, const gfx3DMatrix& aTransform, nsDisplayListBuilder* aBuilder, nsDisplayList& aShadowTree, nsIFrame* aSubdocFrame) { const FrameMetrics* metrics = GetFrameMetrics(aLayer); gfx3DMatrix transform; if (metrics && metrics->IsScrollable()) { const ViewID scrollId = metrics->mScrollId; // We need to figure out the bounds of the scrollable region using the // shadow layer tree from the remote process. The metrics viewport is // defined based on all the transformations of its parent layers and // the scale of the current layer. // Calculate transform for this layer. nsContentView* view = aRootFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId); // XXX why don't we include aLayer->GetTransform() in the inverse-scale here? // This seems wrong, but it doesn't seem to cause bugs! gfx3DMatrix applyTransform = ComputeShadowTreeTransform( aSubdocFrame, aRootFrameLoader, metrics, view->GetViewConfig(), 1 / GetXScale(aTransform), 1 / GetYScale(aTransform)); transform = applyTransform * aLayer->GetTransform() * aTransform; // As mentioned above, bounds calculation also depends on the scale // of this layer. gfx3DMatrix tmpTransform = aTransform; Scale(tmpTransform, GetXScale(applyTransform), GetYScale(applyTransform)); // Calculate rect for this layer based on aTransform. nsRect bounds; { nscoord auPerDevPixel = aSubdocFrame->PresContext()->AppUnitsPerDevPixel(); bounds = metrics->mViewport.ToAppUnits(auPerDevPixel); ApplyTransform(bounds, tmpTransform, auPerDevPixel); } aShadowTree.AppendToTop( new (aBuilder) nsDisplayRemoteShadow(aBuilder, aSubdocFrame, bounds, scrollId)); } else { transform = aLayer->GetTransform() * aTransform; } for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { BuildListForLayer(child, aRootFrameLoader, transform, aBuilder, aShadowTree, aSubdocFrame); } }
// -------------------------------------------------------------- // Called by: GRPage, GRStaff, GRSystem void GDeviceWin32::OffsetOrigin( float x, float y ) { // const float prevX = mOriginX; // const float prevY = mOriginY; mOriginX += x; mOriginY += y; mWinOriginX += (x) * GetXScale(); // (JB) test mWinOriginY += (y) * GetYScale(); ::SetViewportOrgEx( mHDC, RInt( mWinOriginX ), RInt( mWinOriginY ), NULL ); }
// Recursively create a new array of scrollables, preserving any scrollables // that are still in the layer tree. // // aXScale and aYScale are used to calculate any values that need to be in // chrome-document CSS pixels and aren't part of the rendering loop, such as // the initial scroll offset for a new view. static void BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews, nsFrameLoader* aFrameLoader, Layer* aLayer, float aXScale = 1, float aYScale = 1) { ContainerLayer* container = aLayer->AsContainerLayer(); if (!container) return; const FrameMetrics metrics = container->GetFrameMetrics(); const ViewID scrollId = metrics.mScrollId; const gfx3DMatrix transform = aLayer->GetTransform(); aXScale *= GetXScale(transform); aYScale *= GetYScale(transform); if (metrics.IsScrollable()) { nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent() ->PresContext()->AppUnitsPerDevPixel(); nsContentView* view = FindViewForId(oldContentViews, scrollId); if (view) { // View already exists. Be sure to propagate scales for any values // that need to be calculated something in chrome-doc CSS pixels. ViewConfig config = view->GetViewConfig(); aXScale *= config.mXScale; aYScale *= config.mYScale; view->mFrameLoader = aFrameLoader; } else { // View doesn't exist, so generate one. We start the view scroll offset at // the same position as the framemetric's scroll offset from the layer. // The default scale is 1, so no need to propagate scale down. ViewConfig config; config.mScrollOffset = nsPoint( NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.x, auPerDevPixel) * aXScale, NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.y, auPerDevPixel) * aYScale); view = new nsContentView(aFrameLoader, scrollId, config); } view->mViewportSize = nsSize( NSIntPixelsToAppUnits(metrics.mViewport.width, auPerDevPixel) * aXScale, NSIntPixelsToAppUnits(metrics.mViewport.height, auPerDevPixel) * aYScale); view->mContentSize = nsSize( NSIntPixelsToAppUnits(metrics.mContentSize.width, auPerDevPixel) * aXScale, NSIntPixelsToAppUnits(metrics.mContentSize.height, auPerDevPixel) * aYScale); newContentViews[scrollId] = view; } for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { BuildViewMap(oldContentViews, newContentViews, aFrameLoader, child, aXScale, aYScale); } }
// -------------------------------------------------------------- void GDeviceWin32::SetOrigin( float x, float y ) { const float prevX = mOriginX; const float prevY = mOriginY; mOriginX = x; // voir def dans VGDev.cpp mOriginY = y; mWinOriginX += (x - prevX) * GetXScale(); // (JB) test mWinOriginY += (y - prevY) * GetYScale(); // mWinOriginX += (x - prevX) ; // (JB) test // mWinOriginY += (y - prevY) ; ::SetViewportOrgEx( mHDC, RInt( mWinOriginX ), RInt( mWinOriginY ), NULL ); }
// -------------------------------------------------------------- bool GDeviceWin32::Win32ApplyTransform() { const float xScale = GetXScale(); const float yScale = GetYScale(); float width, height, newWidth, newHeight; // - Original code, the standard way to calculate new size. width = (float)GetWidth(); height = (float)GetHeight(); newWidth = width * xScale; newHeight = height * yScale; // Win95 : Coordinates can't be larger than 16 bit. if( mMaximizeAxis || width > 32000 || height > 32000 || newWidth > 32000 || newHeight > 32000 ) { // Then, use the largest extent possible, but under 32000 if( xScale <= 1 ) { width = 32000; newWidth = width * xScale; } else { newWidth = 32000; width = newWidth / xScale; } if( yScale <= 1 ) { height = 32000; newHeight = height * yScale; } else { newHeight = 32000; height = newHeight / yScale; } } BOOL result; // OK for everything but print preview -> result = ::SetWindowExtEx( mHDC, RInt( width ), RInt( height ), NULL ); result = ::SetViewportExtEx( mHDC, RInt( newWidth ), RInt( newHeight ), NULL ); return true; }
/** * Attempts to initialize the graphical video display. Returns 0 on * success, -1 on failure. */ int InitVideo(FCEUGI *gi) { // XXX soules - const? is this necessary? const SDL_VideoInfo *vinf; int error, flags = 0; int doublebuf, xstretch, ystretch, xres, yres, show_fps; FCEUI_printf("Initializing video..."); // load the relevant configuration variables g_config->getOption("SDL.Fullscreen", &s_fullscreen); g_config->getOption("SDL.DoubleBuffering", &doublebuf); #ifdef OPENGL g_config->getOption("SDL.OpenGL", &s_useOpenGL); #endif g_config->getOption("SDL.SpecialFilter", &s_sponge); g_config->getOption("SDL.XStretch", &xstretch); g_config->getOption("SDL.YStretch", &ystretch); g_config->getOption("SDL.LastXRes", &xres); g_config->getOption("SDL.LastYRes", &yres); g_config->getOption("SDL.ClipSides", &s_clipSides); g_config->getOption("SDL.NoFrame", &noframe); g_config->getOption("SDL.ShowFPS", &show_fps); // check the starting, ending, and total scan lines FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline); s_tlines = s_erendline - s_srendline + 1; // check if we should auto-set x/y resolution // check for OpenGL and set the global flags #if OPENGL if(s_useOpenGL && !s_sponge) { flags = SDL_OPENGL; } #endif // initialize the SDL video subsystem if it is not already active if(!SDL_WasInit(SDL_INIT_VIDEO)) { error = SDL_InitSubSystem(SDL_INIT_VIDEO); if(error) { FCEUD_PrintError(SDL_GetError()); return -1; } } s_inited = 1; // shows the cursor within the display window SDL_ShowCursor(1); // determine if we can allocate the display on the video card vinf = SDL_GetVideoInfo(); if(vinf->hw_available) { flags |= SDL_HWSURFACE; } // get the monitor's current resolution if we do not already have it if(s_nativeWidth < 0) { s_nativeWidth = vinf->current_w; } if(s_nativeHeight < 0) { s_nativeHeight = vinf->current_h; } // check to see if we are showing FPS FCEUI_SetShowFPS(show_fps); // check if we are rendering fullscreen if(s_fullscreen) { int no_cursor; g_config->getOption("SDL.NoFullscreenCursor", &no_cursor); flags |= SDL_FULLSCREEN; SDL_ShowCursor(!no_cursor); } else { SDL_ShowCursor(1); } if(noframe) { flags |= SDL_NOFRAME; } // gives the SDL exclusive palette control... ensures the requested colors // flags |= SDL_HWPALETTE; // enable double buffering if requested and we have hardware support #ifdef OPENGL if(s_useOpenGL) { FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n"); if(doublebuf) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); } } else #endif if(doublebuf && (flags & SDL_HWSURFACE)) { flags |= SDL_DOUBLEBUF; } if(s_fullscreen) { int desbpp, autoscale; g_config->getOption("SDL.BitsPerPixel", &desbpp); g_config->getOption("SDL.AutoScale", &autoscale); if (autoscale) { double auto_xscale = GetXScale(xres); double auto_yscale = GetYScale(yres); double native_ratio = ((double)NWIDTH) / s_tlines; double screen_ratio = ((double)xres) / yres; int keep_ratio; g_config->getOption("SDL.KeepRatio", &keep_ratio); // Try to choose resolution if (screen_ratio < native_ratio) { // The screen is narrower than the original. Maximizing width will not clip auto_xscale = auto_yscale = GetXScale(xres); if (keep_ratio) auto_yscale = GetYScale(yres); } else { auto_yscale = auto_xscale = GetYScale(yres); if (keep_ratio) auto_xscale = GetXScale(xres); } s_exs = auto_xscale; s_eys = auto_yscale; } else { g_config->getOption("SDL.XScale", &s_exs); g_config->getOption("SDL.YScale", &s_eys); } g_config->getOption("SDL.SpecialFX", &s_eefx); #ifdef OPENGL if(!s_useOpenGL) { s_exs = (int)s_exs; s_eys = (int)s_eys; } else { desbpp = 0; } // -Video Modes Tag- if(s_sponge) { if(s_sponge == 4 || s_sponge == 5) { s_exs = s_eys = 3; } else { s_exs = s_eys = 2; } s_eefx = 0; if(s_sponge == 1 || s_sponge == 4) { desbpp = 32; } } if((s_useOpenGL && !xstretch) || !s_useOpenGL) #endif if(xres < (NWIDTH * s_exs) || s_exs <= 0.01) { FCEUD_PrintError("xscale out of bounds."); KillVideo(); return -1; } #ifdef OPENGL if((s_useOpenGL && !ystretch) || !s_useOpenGL) #endif if(yres < s_tlines * s_eys || s_eys <= 0.01) { FCEUD_PrintError("yscale out of bounds."); KillVideo(); return -1; } #ifdef OPENGL s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres, s_useOpenGL ? s_nativeHeight : yres, desbpp, flags); #else s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags); #endif if(!s_screen) { FCEUD_PrintError(SDL_GetError()); return -1; } } else { int desbpp; g_config->getOption("SDL.BitsPerPixel", &desbpp); g_config->getOption("SDL.XScale", &s_exs); g_config->getOption("SDL.YScale", &s_eys); g_config->getOption("SDL.SpecialFX", &s_eefx); // -Video Modes Tag- if(s_sponge) { if(s_sponge >= 4) { s_exs = s_eys = 3; } else { s_exs = s_eys = 2; } s_eefx = 0; } #ifdef OPENGL if(!s_useOpenGL) { s_exs = (int)s_exs; s_eys = (int)s_eys; } if(s_exs <= 0.01) { FCEUD_PrintError("xscale out of bounds."); KillVideo(); return -1; } if(s_eys <= 0.01) { FCEUD_PrintError("yscale out of bounds."); KillVideo(); return -1; } if(s_sponge && s_useOpenGL) { FCEUD_PrintError("scalers not compatible with openGL mode."); KillVideo(); return -1; } #endif #if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11) if(noGui == 0) { while (gtk_events_pending()) gtk_main_iteration_do(FALSE); char SDL_windowhack[128]; sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox))); SDL_putenv(SDL_windowhack); // init SDL video if (SDL_WasInit(SDL_INIT_VIDEO)) SDL_QuitSubSystem(SDL_INIT_VIDEO); if ( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "Couldn't init SDL video: %s\n", SDL_GetError()); gtk_main_quit(); } } #endif s_screen = SDL_SetVideoMode((int)(NWIDTH * s_exs), (int)(s_tlines * s_eys), desbpp, flags); if(!s_screen) { FCEUD_PrintError(SDL_GetError()); return -1; } #ifdef _GTK if(noGui == 0) { GtkRequisition req; gtk_widget_size_request(GTK_WIDGET(MainWindow), &req); gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); } #endif } s_curbpp = s_screen->format->BitsPerPixel; if(!s_screen) { FCEUD_PrintError(SDL_GetError()); KillVideo(); return -1; } #if 0 // XXX soules - this would be creating a surface on the video // card, but was commented out for some reason... s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240, s_screen->format->BitsPerPixel, s_screen->format->Rmask, s_screen->format->Gmask, s_screen->format->Bmask, 0); #endif FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n", s_screen->w, s_screen->h, s_screen->format->BitsPerPixel, s_fullscreen ? "full screen" : ""); if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) { FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp); KillVideo(); return -1; } // if the game being run has a name, set it as the window name if(gi) { if(gi->name) { SDL_WM_SetCaption((const char *)gi->name, (const char *)gi->name); } else { SDL_WM_SetCaption(FCEU_NAME_AND_VERSION,"FCE Ultra"); } } // create the surface for displaying graphical messages #ifdef LSB_FIRST s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, 32, 32, 24, 32 * 3, 0xFF, 0xFF00, 0xFF0000, 0x00); #else s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, 32, 32, 24, 32 * 3, 0xFF0000, 0xFF00, 0xFF, 0x00); #endif SDL_WM_SetIcon(s_IconSurface,0); s_paletterefresh = 1; // XXX soules - can't SDL do this for us? // if using more than 8bpp, initialize the conversion routines if(s_curbpp > 8) { InitBlitToHigh(s_curbpp >> 3, s_screen->format->Rmask, s_screen->format->Gmask, s_screen->format->Bmask, s_eefx, s_sponge, 0); #ifdef OPENGL if(s_useOpenGL) { int openGLip; g_config->getOption("SDL.OpenGLip", &openGLip); if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0), s_srendline, s_erendline + 1, s_exs, s_eys, s_eefx, openGLip, xstretch, ystretch, s_screen)) { FCEUD_PrintError("Error initializing OpenGL."); KillVideo(); return -1; } } #endif }
// Recursively create a new array of scrollables, preserving any scrollables // that are still in the layer tree. // // aXScale and aYScale are used to calculate any values that need to be in // chrome-document CSS pixels and aren't part of the rendering loop, such as // the initial scroll offset for a new view. static void BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews, nsFrameLoader* aFrameLoader, Layer* aLayer, float aXScale = 1, float aYScale = 1, float aAccConfigXScale = 1, float aAccConfigYScale = 1) { ContainerLayer* container = aLayer->AsContainerLayer(); if (!container) return; const FrameMetrics metrics = container->GetFrameMetrics(); const ViewID scrollId = metrics.mScrollId; const gfx3DMatrix transform = aLayer->GetTransform(); aXScale *= GetXScale(transform); aYScale *= GetYScale(transform); if (metrics.IsScrollable()) { nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent() ->PresContext()->AppUnitsPerDevPixel(); nsContentView* view = FindViewForId(oldContentViews, scrollId); if (view) { // View already exists. Be sure to propagate scales for any values // that need to be calculated something in chrome-doc CSS pixels. ViewConfig config = view->GetViewConfig(); aXScale *= config.mXScale; aYScale *= config.mYScale; view->mFrameLoader = aFrameLoader; // If scale has changed, then we should update // current scroll offset to new scaled value if (aAccConfigXScale != view->mParentScaleX || aAccConfigYScale != view->mParentScaleY) { float xscroll = 0, yscroll = 0; view->GetScrollX(&xscroll); view->GetScrollY(&yscroll); xscroll = xscroll * (aAccConfigXScale / view->mParentScaleX); yscroll = yscroll * (aAccConfigYScale / view->mParentScaleY); view->ScrollTo(xscroll, yscroll); view->mParentScaleX = aAccConfigXScale; view->mParentScaleY = aAccConfigYScale; } // Collect only config scale values for scroll compensation aAccConfigXScale *= config.mXScale; aAccConfigYScale *= config.mYScale; } else { // View doesn't exist, so generate one. We start the view scroll offset at // the same position as the framemetric's scroll offset from the layer. // The default scale is 1, so no need to propagate scale down. ViewConfig config; config.mScrollOffset = nsPoint( NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.x, auPerDevPixel) * aXScale, NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.y, auPerDevPixel) * aYScale); view = new nsContentView(aFrameLoader, scrollId, config); view->mParentScaleX = aAccConfigXScale; view->mParentScaleY = aAccConfigYScale; } view->mViewportSize = nsSize( NSIntPixelsToAppUnits(metrics.mViewport.width, auPerDevPixel) * aXScale, NSIntPixelsToAppUnits(metrics.mViewport.height, auPerDevPixel) * aYScale); view->mContentSize = nsSize( nsPresContext::CSSPixelsToAppUnits(metrics.mCSSContentSize.width) * aXScale, nsPresContext::CSSPixelsToAppUnits(metrics.mCSSContentSize.height) * aYScale); newContentViews[scrollId] = view; } for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { BuildViewMap(oldContentViews, newContentViews, aFrameLoader, child, aXScale, aYScale, aAccConfigXScale, aAccConfigYScale); } }