Ejemplo n.º 1
0
static inline int find_num_frames(int rate, int latency)
{
   int frames = (rate * latency) / 1000;
   // SDL only likes 2^n sized buffers.
   return next_pow2(frames);
}
Ejemplo n.º 2
0
static bool psp_frame(void *data, const void *frame,
      unsigned width, unsigned height, uint64_t frame_count,
      unsigned pitch, const char *msg)
{
#ifdef DISPLAY_FPS
   uint32_t diff;
   static uint64_t currentTick,lastTick;
   static int frames;
   static float fps                        = 0.0;
#endif
   static struct retro_perf_counter psp_frame_run = {0};
   static char fps_txt[128]                = {0};
   static char fps_text_buf[128]           = {0};
   psp1_video_t *psp                       = (psp1_video_t*)data;
   settings_t *settings                    = config_get_ptr();

   if (!width || !height)
      return false;

   if (((uint32_t)frame&0x04000000) || (frame == RETRO_HW_FRAME_BUFFER_VALID))
      psp->hw_render = true;
   else if (frame)
      psp->hw_render = false;

   if (!psp->hw_render)
      sceGuSync(0, 0); /* let the core decide when to sync when HW_RENDER */

   pspDebugScreenSetBase(psp->draw_buffer);

   pspDebugScreenSetXY(0,0);

   video_monitor_get_fps(fps_txt, sizeof(fps_txt),
         settings->fps_show ? fps_text_buf : NULL,
         settings->fps_show ? sizeof(fps_text_buf) : 0);

   if(settings->fps_show)
   {
      pspDebugScreenSetXY(68 - strlen(fps_text_buf) - 1,0);
      pspDebugScreenPuts(fps_text_buf);
      pspDebugScreenSetXY(0,1);
   }

   if (msg)
      pspDebugScreenPuts(msg);

   if ((psp->vsync)&&(psp->vblank_not_reached))
      sceDisplayWaitVblankStart();

   psp->vblank_not_reached = true;

#ifdef DISPLAY_FPS
   frames++;
   sceRtcGetCurrentTick(&currentTick);
   diff = currentTick - lastTick;
   if(diff > 1000000)
   {
      fps = (float)frames * 1000000.0 / diff;
      lastTick = currentTick;
      frames = 0;
   }

   pspDebugScreenSetXY(0,0);
   pspDebugScreenPrintf("%f", fps);
#endif

   psp->draw_buffer = FROM_GU_POINTER(sceGuSwapBuffers());

   rarch_perf_init(&psp_frame_run, "psp_frame_run");
   retro_perf_start(&psp_frame_run);

   if (psp->should_resize)
      psp_update_viewport(psp);

   psp_set_tex_coords(psp->frame_coords, width, height);

   sceGuStart(GU_DIRECT, psp->main_dList);

   sceGuTexFilter(psp->tex_filter, psp->tex_filter);
   sceGuClear(GU_COLOR_BUFFER_BIT);

   /* frame in VRAM ? texture/palette was 
    * set in core so draw directly */
   if (psp->hw_render) 
      sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | 
            GU_TRANSFORM_2D, PSP_FRAME_VERTEX_COUNT, NULL,
            (void*)(psp->frame_coords));
   else
   {
      if (frame)
      {
         sceKernelDcacheWritebackRange(frame,pitch * height);
         sceGuCopyImage(psp->rgb32? GU_PSM_8888 : GU_PSM_5650, ((u32)frame & 0xF) >> psp->bpp_log2,
               0, width, height, pitch >> psp->bpp_log2,
               (void*)((u32)frame & ~0xF), 0, 0, width, psp->texture);
      }
      sceGuTexImage(0, next_pow2(width), next_pow2(height), width, psp->texture);
      sceGuCallList(psp->frame_dList);
   }

   sceGuFinish();

   retro_perf_stop(&psp_frame_run);

   if(psp->menu.active)
   {
      sceGuSendList(GU_TAIL, psp->menu.dList, &(psp->menu.context_storage));
      sceGuSync(0, 0);
   }

   return true;
}
Ejemplo n.º 3
0
static bool psp_frame(void *data, const void *frame,
      unsigned width, unsigned height, unsigned pitch, const char *msg)
{
   static char fps_txt[128], fps_text_buf[128];
   psp1_video_t *psp = (psp1_video_t*)data;

#ifdef DISPLAY_FPS
   static uint64_t currentTick,lastTick;
   static float fps=0.0;
   static int frames;
#endif

   if (!width || !height)
      return false;

   if (((uint32_t)frame&0x04000000) || (frame == RETRO_HW_FRAME_BUFFER_VALID))
      psp->hw_render = true;
   else if (frame)
      psp->hw_render = false;

   if (!psp->hw_render)
      sceGuSync(0, 0); // let the core decide when to sync when HW_RENDER

   pspDebugScreenSetBase(psp->draw_buffer);

   pspDebugScreenSetXY(0,0);

   if(g_settings.fps_show)
   {
      gfx_get_fps(fps_txt, sizeof(fps_txt), fps_text_buf, sizeof(fps_text_buf));
      pspDebugScreenSetXY(68 - strlen(fps_text_buf) - 1,0);
      pspDebugScreenPuts(fps_text_buf);
      pspDebugScreenSetXY(0,1);
   }
   else
      gfx_get_fps(fps_txt, sizeof(fps_txt), NULL, 0);

   if (msg)
      pspDebugScreenPuts(msg);

   if ((psp->vsync)&&(psp->vblank_not_reached))
      sceDisplayWaitVblankStart();

   psp->vblank_not_reached = true;

#ifdef DISPLAY_FPS
   frames++;
   sceRtcGetCurrentTick(&currentTick);
   uint32_t diff = currentTick - lastTick;
   if(diff > 1000000)
   {
      fps = (float)frames * 1000000.0 / diff;
      lastTick = currentTick;
      frames = 0;
   }

   pspDebugScreenSetXY(0,0);
   pspDebugScreenPrintf("%f", fps);
#endif

   psp->draw_buffer = FROM_GU_POINTER(sceGuSwapBuffers());
   g_extern.frame_count++;


   RARCH_PERFORMANCE_INIT(psp_frame_run);
   RARCH_PERFORMANCE_START(psp_frame_run);

   if (psp->should_resize)
      psp_update_viewport(psp);

   psp_set_tex_coords(psp->frame_coords, width, height);

   sceGuStart(GU_DIRECT, psp->main_dList);

   sceGuTexFilter(psp->tex_filter, psp->tex_filter);
   sceGuClear(GU_COLOR_BUFFER_BIT);

   if (psp->hw_render) // frame in VRAM ? texture/palette was set in core so draw directly
      sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, PSP_FRAME_VERTEX_COUNT, NULL, (void*)(psp->frame_coords));
   else
   {
      if (frame!=NULL)
      {
         sceKernelDcacheWritebackRange(frame,pitch * height);
         sceGuCopyImage(GU_PSM_5650, ((u32)frame & 0xF) >> psp->bpp_log2, 0, width, height, pitch >> psp->bpp_log2, (void*)((u32)frame & ~0xF), 0, 0, width, psp->texture);
      }
      sceGuTexImage(0, next_pow2(width), next_pow2(height), width, psp->texture);
      sceGuCallList(psp->frame_dList);
   }
Ejemplo n.º 4
0
void init_video_input(void)
{
   rarch_init_filter(g_extern.system.pix_fmt);

   init_shader_dir();

   const struct retro_game_geometry *geom = &g_extern.system.av_info.geometry;
   unsigned max_dim = max(geom->max_width, geom->max_height);
   unsigned scale = next_pow2(max_dim) / RARCH_SCALE_BASE;
   scale = max(scale, 1);

   if (g_extern.filter.filter)
      scale = g_extern.filter.scale;

   // Update core-dependent aspect ratio values.
   gfx_set_square_pixel_viewport(geom->base_width, geom->base_height);
   gfx_set_core_viewport();
   gfx_set_config_viewport();

   // Update CUSTOM viewport.
   rarch_viewport_t *custom_vp = &g_extern.console.screen.viewports.custom_vp;
   if (g_settings.video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
   {
      float default_aspect = aspectratio_lut[ASPECT_RATIO_CORE].value;
      aspectratio_lut[ASPECT_RATIO_CUSTOM].value = (custom_vp->width && custom_vp->height) ?
         (float)custom_vp->width / custom_vp->height : default_aspect;
   }

   g_extern.system.aspect_ratio = aspectratio_lut[g_settings.video.aspect_ratio_idx].value;

   unsigned width;
   unsigned height;
   if (g_settings.video.fullscreen)
   {
      width = g_settings.video.fullscreen_x;
      height = g_settings.video.fullscreen_y;
   }
   else
   {
      if (g_settings.video.force_aspect)
      {
         // Do rounding here to simplify integer scale correctness.
         unsigned base_width = roundf(geom->base_height * g_extern.system.aspect_ratio);
         width = roundf(base_width * g_settings.video.scale);
         height = roundf(geom->base_height * g_settings.video.scale);
      }
      else
      {
         width = roundf(geom->base_width * g_settings.video.scale);
         height = roundf(geom->base_height * g_settings.video.scale);
      }
   }

   if (width && height)
      RARCH_LOG("Video @ %ux%u\n", width, height);
   else
      RARCH_LOG("Video @ fullscreen\n");

   driver.display_type  = RARCH_DISPLAY_NONE;
   driver.video_display = 0;
   driver.video_window  = 0;

   if (!init_video_pixel_converter(RARCH_SCALE_BASE * scale))
   {
      RARCH_ERR("Failed to initialize pixel converter.\n");
      rarch_fail(1, "init_video_input()");
   }

   video_info_t video = {0};
   video.width = width;
   video.height = height;
   video.fullscreen = g_settings.video.fullscreen;
   video.vsync = g_settings.video.vsync && !g_extern.system.force_nonblock;
   video.force_aspect = g_settings.video.force_aspect;
#ifdef GEKKO
   video.viwidth = g_settings.video.viwidth;
#endif
   video.smooth = g_settings.video.smooth;
   video.input_scale = scale;
   video.rgb32 = g_extern.filter.filter ? g_extern.filter.out_rgb32 : (g_extern.system.pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);

   const input_driver_t *tmp = driver.input;
   find_video_driver(); // Need to grab the "real" video driver interface on a reinit.
#ifdef HAVE_THREADS
   if (g_settings.video.threaded && !g_extern.system.hw_render_callback.context_type) // Can't do hardware rendering with threaded driver currently.
   {
      RARCH_LOG("Starting threaded video driver ...\n");
      if (!rarch_threaded_video_init(&driver.video, &driver.video_data,
               &driver.input, &driver.input_data,
               driver.video, &video))
      {
         RARCH_ERR("Cannot open threaded video driver ... Exiting ...\n");
         rarch_fail(1, "init_video_input()");
      }
   }
   else
#endif
      driver.video_data = driver.video->init(&video, &driver.input, &driver.input_data);

   if (!driver.video_data)
   {
      RARCH_ERR("Cannot open video driver ... Exiting ...\n");
      rarch_fail(1, "init_video_input()");
   }

   driver.video_poke = NULL;
   if (driver.video->poke_interface)
      driver.video->poke_interface(driver.video_data, &driver.video_poke);

   // Force custom viewport to have sane parameters.
   if (driver.video->viewport_info && (!custom_vp->width || !custom_vp->height))
   {
      custom_vp->width = width;
      custom_vp->height = height;
      driver.video->viewport_info(driver.video_data, custom_vp);
   }

   if (driver.video->set_rotation)
      driver.video->set_rotation(driver.video_data, (g_settings.video.rotation + g_extern.system.rotation) % 4);

#ifdef HAVE_X11
   if (driver.display_type == RARCH_DISPLAY_X11)
   {
      RARCH_LOG("Suspending screensaver (X11).\n");
      x11_suspend_screensaver(driver.video_window);
   }
#endif

   // Video driver didn't provide an input driver so we use configured one.
   if (!driver.input)
   {

      RARCH_LOG("Graphics driver did not initialize an input driver. Attempting to pick a suitable driver.\n");

      if (tmp)
         driver.input = tmp;
      else
         find_input_driver();

      if (driver.input)
      {
         driver.input_data = driver.input->init();
         if (!driver.input_data)
         {
            RARCH_ERR("Cannot initialize input driver. Exiting ...\n");
            rarch_fail(1, "init_video_input()");
         }
      }
      else
      {
         // This should never really happen as tmp (driver.input) is always found before this in find_driver_input(),
         // or we have aborted in a similar fashion anyways.
         rarch_fail(1, "init_video_input()");
      }
   }

#ifdef HAVE_OVERLAY
   rarch_main_command(RARCH_CMD_OVERLAY_DEINIT);
   rarch_main_command(RARCH_CMD_OVERLAY_INIT);
#endif

   g_extern.measure_data.frame_time_samples_count = 0;
}
Ejemplo n.º 5
0
void clim_draw_texture(const sf2d_texture *texture, int x, int y)
{
    sf2d_draw_texture_part_scale(texture, x, y+texture->height, 0, next_pow2(texture->height) - texture->height, texture->width, texture->height, 1, -1);
}
Ejemplo n.º 6
0
static bool d3d_init_chain(d3d_video_t *d3d, const video_info_t *video_info)
{
   LPDIRECT3DDEVICE d3dr = (LPDIRECT3DDEVICE)d3d->dev;
   // Setup information for first pass.
   LinkInfo link_info = {0};

   link_info.pass = &d3d->shader.pass[0];
   link_info.tex_w = link_info.tex_h = video_info->input_scale * RARCH_SCALE_BASE;

   d3d_deinit_chain(d3d);
   d3d->chain = new renderchain_t();
   if (!d3d->chain)
      return false;

   if (!renderchain_init(d3d->chain, &d3d->video_info, d3dr, d3d->cgCtx, &d3d->final_viewport, &link_info,
            d3d->video_info.rgb32 ? ARGB : RGB565))
   {
      RARCH_ERR("[D3D9]: Failed to init render chain.\n");
      return false;
   }

   unsigned current_width = link_info.tex_w;
   unsigned current_height = link_info.tex_h;
   unsigned out_width = 0;
   unsigned out_height = 0;

   for (unsigned i = 1; i < d3d->shader.passes; i++)
   {
      renderchain_convert_geometry(d3d->chain, &link_info,
            out_width, out_height,
            current_width, current_height, &d3d->final_viewport);

      link_info.pass = &d3d->shader.pass[i];
      link_info.tex_w = next_pow2(out_width);
      link_info.tex_h = next_pow2(out_height);

      current_width = out_width;
      current_height = out_height;

      if (!renderchain_add_pass(d3d->chain, &link_info))
      {
         RARCH_ERR("[D3D9]: Failed to add pass.\n");
         return false;
      }
   }

   if (!d3d_init_luts(d3d))
   {
      RARCH_ERR("[D3D9]: Failed to init LUTs.\n");
      return false;
   }

#ifndef DONT_HAVE_STATE_TRACKER
   if (!d3d_init_imports(d3d))
   {
      RARCH_ERR("[D3D9]: Failed to init imports.\n");
      return false;
   }
#endif

   return true;
}
Ejemplo n.º 7
0
void rarch_init_filter(enum retro_pixel_format colfmt)
{
   rarch_deinit_filter();
#ifdef HAVE_FILTERS_BUILTIN
   if (!g_settings.video.filter_idx)
#else
   if (!*g_settings.video.filter_path)
#endif
      return;

   // Deprecated format. Gets pre-converted.
   if (colfmt == RETRO_PIXEL_FORMAT_0RGB1555)
      colfmt = RETRO_PIXEL_FORMAT_RGB565;

   if (g_extern.system.hw_render_callback.context_type)
   {
      RARCH_WARN("Cannot use CPU filters when hardware rendering is used.\n");
      return;
   }

   struct retro_game_geometry *geom = &g_extern.system.av_info.geometry;
   unsigned width   = geom->max_width;
   unsigned height  = geom->max_height;
   unsigned pow2_x  = 0;
   unsigned pow2_y  = 0;
   unsigned maxsize = 0;

#ifdef HAVE_FILTERS_BUILTIN
   RARCH_LOG("Loading softfilter %d\n", g_settings.video.filter_idx);
#else
   RARCH_LOG("Loading softfilter from \"%s\"\n", g_settings.video.filter_path);
#endif
   g_extern.filter.filter = rarch_softfilter_new(g_settings.video.filter_path,
         RARCH_SOFTFILTER_THREADS_AUTO, colfmt, width, height);

   if (!g_extern.filter.filter)
   {
#ifdef HAVE_FILTERS_BUILTIN
      RARCH_LOG("Loading softfilter %d\n", g_settings.video.filter_idx);
#else
      RARCH_ERR("Failed to load filter \"%s\"\n", g_settings.video.filter_path);
#endif
      return;
   }

   rarch_softfilter_get_max_output_size(g_extern.filter.filter, &width, &height);
   pow2_x  = next_pow2(width);
   pow2_y  = next_pow2(height);
   maxsize = max(pow2_x, pow2_y); 
   g_extern.filter.scale = maxsize / RARCH_SCALE_BASE;

   g_extern.filter.out_rgb32 = rarch_softfilter_get_output_format(g_extern.filter.filter) == RETRO_PIXEL_FORMAT_XRGB8888;
   g_extern.filter.out_bpp = g_extern.filter.out_rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);

   // TODO: Aligned output.
   g_extern.filter.buffer = malloc(width * height * g_extern.filter.out_bpp);
   if (!g_extern.filter.buffer)
      goto error;

   return;

error:
   RARCH_ERR("Softfilter init failed.\n");
   rarch_deinit_filter();
}
Ejemplo n.º 8
0
SDL_Window* set_video_mode(int w, int h, int flags)
{
    static SDL_Window* wnd = NULL;
    static SDL_GLContext ctx = NULL;
    static int wnd_flags = 0;

    if(wnd) {
        SDL_DisplayMode mode;
        if(SDL_GetWindowDisplayMode(wnd, &mode) == 0) {
            mode.w = w;
            mode.h = h;
            if(SDL_SetWindowDisplayMode(wnd, &mode) == 0) {
                SDL_SetWindowSize(wnd, w, h);
                SDL_SetWindowFullscreen(wnd, flags&SDL_WINDOW_FULLSCREEN);
                SDL_SetWindowPosition(wnd, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
                return wnd;
            } else {
                fprintf(stderr, "ERROR: Failed to set window display mode. Destroying window and creating a new one.\n");
            }

        } else {
            fprintf(stderr, "ERROR: Failed to get window display mode. Destroying window and creating a new one.\n");
        }
    }

    wnd_flags = flags;

    graphics::texture::unbuild_all();
#if defined(USE_SHADERS)
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);

    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);

    if(g_msaa > 0) {
        if(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) != 0) {
            std::cerr << "MSAA(" << g_msaa << ") requested but mutlisample buffer couldn't be allocated." << std::endl;
        } else {
            size_t msaa = next_pow2(g_msaa);
            std::cerr << "Requesting MSAA of " << msaa;
            if(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa) != 0) {
                std::cerr << " -- Failure, disabled.";
            }
            std::cerr << std::endl;
        }
    }
#endif
    if(global_renderer) {
        SDL_DestroyRenderer(global_renderer);
        global_renderer = NULL;
    }
    if(ctx) {
        SDL_GL_DeleteContext(ctx);
        ctx = NULL;
    }
    if(wnd) {
        SDL_DestroyWindow(wnd);
        global_main_window = wnd = NULL;
    }
    if(!(flags & CLEANUP_WINDOW_CONTEXT)) {
        global_main_window = wnd = SDL_CreateWindow(module::get_module_pretty_name().c_str(),
                                   SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, flags);
        ctx = SDL_GL_CreateContext(wnd);
        global_renderer = SDL_CreateRenderer(wnd, -1, SDL_RENDERER_ACCELERATED);
#if defined(__GLEW_H__)
        GLenum glew_status = glewInit();
        ASSERT_EQ(glew_status, GLEW_OK);
#endif

        reset_opengl_state();
        graphics::texture::rebuild_all();
        texture_frame_buffer::rebuild();
    }
#if defined(USE_SHADERS)
    int depth_size, stencil_size;
    SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth_size);
    SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil_size);
    std::cerr << "Depth buffer size: " << depth_size << std::endl;
    std::cerr << "Stenicl buffer size: " << stencil_size << std::endl;
    int depth;
    glGetIntegerv(GL_DEPTH_BITS, &depth);
    std::cerr << "Depth(from GL) buffer size: " << depth << std::endl;

    if(g_msaa > 0 && SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &g_msaa_set) == 0) {
        std::cerr << "Actual MSAA: " << g_msaa_set << std::endl;
    }
#endif
    return wnd;
}
Ejemplo n.º 9
0
static void *sl_init(const char *device, unsigned rate, unsigned latency)
{
   (void)device;

   SLDataFormat_PCM fmt_pcm = {0};
   SLDataSource audio_src   = {0};
   SLDataSink audio_sink    = {0};

   SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {0};
   SLDataLocator_OutputMix loc_outmix              = {0};

   SLInterfaceID id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
   SLboolean req    = SL_BOOLEAN_TRUE;

   SLresult res = 0;
   sl_t *sl = (sl_t*)calloc(1, sizeof(sl_t));
   if (!sl)
      goto error;

   RARCH_LOG("[SLES]: Requested audio latency: %d ms.", latency);

   GOTO_IF_FAIL(slCreateEngine(&sl->engine_object, 0, NULL, 0, NULL, NULL));
   GOTO_IF_FAIL(SLObjectItf_Realize(sl->engine_object, SL_BOOLEAN_FALSE));
   GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->engine_object, SL_IID_ENGINE, &sl->engine));

   GOTO_IF_FAIL(SLEngineItf_CreateOutputMix(sl->engine, &sl->output_mix, 0, NULL, NULL));
   GOTO_IF_FAIL(SLObjectItf_Realize(sl->output_mix, SL_BOOLEAN_FALSE));

   if (g_settings.audio.block_frames)
      sl->buf_size = g_settings.audio.block_frames * 4;
   else
      sl->buf_size = next_pow2(32 * latency);

   sl->buf_count = (latency * 4 * out_rate + 500) / 1000;
   sl->buf_count = (sl->buf_count + sl->buf_size / 2) / sl->buf_size;

   sl->buffer = (uint8_t**)calloc(sizeof(uint8_t*), sl->buf_count);
   if (!sl->buffer)
      goto error;

   sl->buffer_chunk = (uint8_t*)calloc(sl->buf_count, sl->buf_size);
   if (!sl->buffer_chunk)
      goto error;

   for (unsigned i = 0; i < sl->buf_count; i++)
      sl->buffer[i] = sl->buffer_chunk + i * sl->buf_size;

   RARCH_LOG("[SLES]: Setting audio latency: Block size = %u, Blocks = %u, Total = %u ...\n",
         sl->buf_size, sl->buf_count, sl->buf_size * sl->buf_count);

   fmt_pcm.formatType    = SL_DATAFORMAT_PCM;
   fmt_pcm.numChannels   = 2;
   fmt_pcm.samplesPerSec = rate * 1000; // Samplerate is in milli-Hz.
   fmt_pcm.bitsPerSample = 16;
   fmt_pcm.containerSize = 16;
   fmt_pcm.channelMask   = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
   fmt_pcm.endianness    = SL_BYTEORDER_LITTLEENDIAN; // Android only.

   audio_src.pLocator = &loc_bufq;
   audio_src.pFormat  = &fmt_pcm;

   loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
   loc_bufq.numBuffers  = sl->buf_count;

   loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
   loc_outmix.outputMix   = sl->output_mix;

   audio_sink.pLocator = &loc_outmix;

   GOTO_IF_FAIL(SLEngineItf_CreateAudioPlayer(sl->engine, &sl->buffer_queue_object,
            &audio_src, &audio_sink,
            1, &id, &req));
   GOTO_IF_FAIL(SLObjectItf_Realize(sl->buffer_queue_object, SL_BOOLEAN_FALSE));

   GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
            &sl->buffer_queue));

   sl->cond = scond_new();
   sl->lock = slock_new();

   (*sl->buffer_queue)->RegisterCallback(sl->buffer_queue, opensl_callback, sl);

   // Enqueue a bit to get stuff rolling.
   sl->buffered_blocks = sl->buf_count;
   sl->buffer_index = 0;
   for (unsigned i = 0; i < sl->buf_count; i++)
      (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[i], sl->buf_size);

   GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_PLAY, &sl->player));
   GOTO_IF_FAIL(SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING));

   return sl;

error:
   RARCH_ERR("Couldn't initialize OpenSL ES driver, error code: [%d].\n", (int)res);
   sl_free(sl);
   return NULL;
}
Ejemplo n.º 10
0
void gl_init_fbo(gl_t *gl, unsigned width, unsigned height)
{
   // No need to use FBOs.
   if (!g_settings.video.render_to_texture && gl_shader_num() == 0)
      return;

   struct gl_fbo_scale scale, scale_last;
   gl_shader_scale(1, &scale);
   gl_shader_scale(gl_shader_num(), &scale_last);

   // No need to use FBOs.
   if (gl_shader_num() == 1 && !scale.valid && !g_settings.video.render_to_texture)
      return;

   if (!load_fbo_proc())
   {
      RARCH_ERR("Failed to locate FBO functions. Won't be able to use render-to-texture.\n");
      return;
   }

   gl->fbo_pass = gl_shader_num() - 1;
   if (scale_last.valid)
      gl->fbo_pass++;

   if (gl->fbo_pass <= 0)
      gl->fbo_pass = 1;

   if (!scale.valid)
   {
      scale.scale_x = g_settings.video.fbo_scale_x;
      scale.scale_y = g_settings.video.fbo_scale_y;
      scale.type_x  = scale.type_y = RARCH_SCALE_INPUT;
      scale.valid   = true;
   }

   gl->fbo_scale[0] = scale;

   for (int i = 1; i < gl->fbo_pass; i++)
   {
      gl_shader_scale(i + 1, &gl->fbo_scale[i]);

      if (!gl->fbo_scale[i].valid)
      {
         gl->fbo_scale[i].scale_x = gl->fbo_scale[i].scale_y = 1.0f;
         gl->fbo_scale[i].type_x  = gl->fbo_scale[i].type_y  = RARCH_SCALE_INPUT;
         gl->fbo_scale[i].valid   = true;
      }
   }

   gl_compute_fbo_geometry(gl, width, height, gl->win_width, gl->win_height);

   for (int i = 0; i < gl->fbo_pass; i++)
   {
      gl->fbo_rect[i].width  = next_pow2(gl->fbo_rect[i].img_width);
      gl->fbo_rect[i].height = next_pow2(gl->fbo_rect[i].img_height);
      RARCH_LOG("Creating FBO %d @ %ux%u\n", i, gl->fbo_rect[i].width, gl->fbo_rect[i].height);
   }

   gl_create_fbo_textures(gl);
   if (!gl_create_fbo_targets(gl))
   {
      glDeleteTextures(gl->fbo_pass, gl->fbo_texture);
      return;
   }

   gl->fbo_inited = true;
}
Ejemplo n.º 11
0
 inline uint32_t required_capacity(uint32_t max_count)
 {
     return next_pow2((uint32_t)ceilf(max_count / load_factor));
 }
Ejemplo n.º 12
0
/* Set up render to texture. */
void gl2_renderchain_init(
      gl_t *gl, void *chain_data,
      unsigned fbo_width, unsigned fbo_height)
{
   int i;
   unsigned width, height;
   video_shader_ctx_scale_t scaler;
   video_shader_ctx_info_t shader_info;
   struct gfx_fbo_scale scale, scale_last;
   gl2_renderchain_t *chain = (gl2_renderchain_t*)chain_data;

   if (!video_shader_driver_info(&shader_info))
      return;

   if (!gl || shader_info.num == 0)
      return;

   video_driver_get_size(&width, &height);

   scaler.idx   = 1;
   scaler.scale = &scale;

   video_shader_driver_scale(&scaler);

   scaler.idx   = shader_info.num;
   scaler.scale = &scale_last;

   video_shader_driver_scale(&scaler);

   /* we always want FBO to be at least initialized on startup for consoles */
   if (shader_info.num == 1 && !scale.valid)
      return;

   if (!gl->has_fbo)
   {
      RARCH_ERR("[GL]: Failed to locate FBO functions. Won't be able to use render-to-texture.\n");
      return;
   }

   chain->fbo_pass = shader_info.num - 1;
   if (scale_last.valid)
      chain->fbo_pass++;

   if (!scale.valid)
   {
      scale.scale_x = 1.0f;
      scale.scale_y = 1.0f;
      scale.type_x  = scale.type_y = RARCH_SCALE_INPUT;
      scale.valid   = true;
   }

   chain->fbo_scale[0] = scale;

   for (i = 1; i < chain->fbo_pass; i++)
   {
      scaler.idx   = i + 1;
      scaler.scale = &chain->fbo_scale[i];

      video_shader_driver_scale(&scaler);

      if (!chain->fbo_scale[i].valid)
      {
         chain->fbo_scale[i].scale_x = chain->fbo_scale[i].scale_y = 1.0f;
         chain->fbo_scale[i].type_x  = chain->fbo_scale[i].type_y  =
            RARCH_SCALE_INPUT;
         chain->fbo_scale[i].valid   = true;
      }
   }

   gl2_renderchain_recompute_pass_sizes(gl,
         chain_data,
         fbo_width, fbo_height, width, height);

   for (i = 0; i < chain->fbo_pass; i++)
   {
      gl->fbo_rect[i].width  = next_pow2(gl->fbo_rect[i].img_width);
      gl->fbo_rect[i].height = next_pow2(gl->fbo_rect[i].img_height);
      RARCH_LOG("[GL]: Creating FBO %d @ %ux%u\n", i,
            gl->fbo_rect[i].width, gl->fbo_rect[i].height);
   }

   gl->fbo_feedback_enable = video_shader_driver_get_feedback_pass(
         &gl->fbo_feedback_pass);

   if (gl->fbo_feedback_enable && gl->fbo_feedback_pass
         < (unsigned)chain->fbo_pass)
   {
      RARCH_LOG("[GL]: Creating feedback FBO %d @ %ux%u\n", i,
            gl->fbo_rect[gl->fbo_feedback_pass].width,
            gl->fbo_rect[gl->fbo_feedback_pass].height);
   }
   else if (gl->fbo_feedback_enable)
   {
      RARCH_WARN("[GL]: Tried to create feedback FBO of pass #%u, but there are only %d FBO passes. Will use input texture as feedback texture.\n",
              gl->fbo_feedback_pass, chain->fbo_pass);
      gl->fbo_feedback_enable = false;
   }

   gl_create_fbo_textures(gl, chain);
   if (!gl || !gl_create_fbo_targets(gl, chain))
   {
      glDeleteTextures(chain->fbo_pass, chain->fbo_texture);
      RARCH_ERR("[GL]: Failed to create FBO targets. Will continue without FBO.\n");
      return;
   }

   gl->fbo_inited = true;
}
Ejemplo n.º 13
0
static void *gl_raster_font_init_font(void *data,
      const char *font_path, float font_size)
{
   unsigned width, height;
   uint8_t *tmp_buffer;
   const struct font_atlas *atlas = NULL;
   gl_raster_t *font = (gl_raster_t*)calloc(1, sizeof(*font));

   if (!font)
      return NULL;

   font->gl = (gl_t*)data;

   if (!font_renderer_create_default(&font->font_driver,
            &font->font_data, font_path, font_size))
   {
      RARCH_WARN("Couldn't init font renderer.\n");
      free(font);
      return NULL;
   }

   glGenTextures(1, &font->tex);
   glBindTexture(GL_TEXTURE_2D, font->tex);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

   atlas = font->font_driver->get_atlas(font->font_data);

   width = next_pow2(atlas->width);
   height = next_pow2(atlas->height);

   /* Ideally, we'd use single component textures, but the 
    * difference in ways to do that between core GL and GLES/legacy GL
    * is too great to bother going down that route. */
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
         0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

   tmp_buffer = (uint8_t*)malloc(atlas->width * atlas->height * 4);

   if (tmp_buffer)
   {
      unsigned i;
      uint8_t       *dst = tmp_buffer;
      const uint8_t *src = atlas->buffer;

      for (i = 0; i < atlas->width * atlas->height; i++)
      {
         *dst++ = 0xff;
         *dst++ = 0xff;
         *dst++ = 0xff;
         *dst++ = *src++;
      }

      glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, atlas->width,
            atlas->height, GL_RGBA, GL_UNSIGNED_BYTE, tmp_buffer);
      free(tmp_buffer);
   }

   font->tex_width  = width;
   font->tex_height = height;

   glBindTexture(GL_TEXTURE_2D, font->gl->texture[font->gl->tex_index]);

   return font;
}
Ejemplo n.º 14
0
    //--------------------------------------------------------------------------
    bool init(
        uword fixed_size_entries,
        uword fixed_size_entry_size,
        bool  use_heap
        )
    {
        assert ((fixed_size_entries && fixed_size_entry_size) || use_heap);
        assert (!m_fixed_begin && !m_use_heap);

        uword entries  = 0;
        uword entry_sz = 0;
        uword bsz      = 0;

        if (fixed_size_entries && fixed_size_entry_size)
        {
            entries  = next_pow2 (fixed_size_entries);
            entry_sz = next_pow2 (fixed_size_entry_size);

            if ((entries < fixed_size_entries) ||
                (entry_sz < fixed_size_entry_size)
                )
            {
                return false;
            }
            bsz = entries * entry_sz;
            if ((bsz / entries) != entry_sz)
            {
                return false;
            }
        }

        if (!bsz)
        {
            zero();
            m_use_heap = use_heap;
            return true;
        }

        m_fixed_begin  = (u8*) ::operator new (bsz, std::nothrow);
        if (!m_fixed_begin)
        {
            return false;
        }
        try
        {
            m_list.construct (entries);
        }
        catch (...)
        {
            free();
            return false;
        }
        m_fixed_end   = m_fixed_begin + bsz;
        m_entry_size  = entry_sz;
        m_use_heap    = use_heap;
        for (uword i = 0; i < entries; ++i)
        {
            m_list->bounded_push (m_fixed_begin + (i * m_entry_size));
        }
        return true;
    }
Ejemplo n.º 15
0
/**
 * recording_init:
 *
 * Initializes recording.
 *
 * Returns: true (1) if successful, otherwise false (0).
 **/
bool recording_init(void)
{
   char recording_file[PATH_MAX_LENGTH] = {0};
   struct ffemu_params params           = {0};
   global_t *global                     = global_get_ptr();
   driver_t *driver                     = driver_get_ptr();
   settings_t *settings                 = config_get_ptr();
   struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
   const struct retro_hw_render_callback *hw_render = 
      (const struct retro_hw_render_callback*)video_driver_callback();
   bool *recording_enabled              = recording_is_enabled();

   if (!*recording_enabled)
      return false;

   if (global->inited.core.type == CORE_TYPE_DUMMY)
   {
      RARCH_WARN("%s\n", msg_hash_to_str(MSG_USING_LIBRETRO_DUMMY_CORE_RECORDING_SKIPPED));
      return false;
   }

   if (!settings->video.gpu_record && hw_render->context_type)
   {
      RARCH_WARN("%s.\n", msg_hash_to_str(MSG_HW_RENDERED_MUST_USE_POSTSHADED_RECORDING));
      return false;
   }

   RARCH_LOG("%s: FPS: %.4f, Sample rate: %.4f\n",
         msg_hash_to_str(MSG_CUSTOM_TIMING_GIVEN),
         (float)av_info->timing.fps,
         (float)av_info->timing.sample_rate);

   strlcpy(recording_file, global->record.path, sizeof(recording_file));

   if (global->record.use_output_dir)
      fill_pathname_join(recording_file,
            global->record.output_dir,
            global->record.path, sizeof(recording_file));

   params.out_width  = av_info->geometry.base_width;
   params.out_height = av_info->geometry.base_height;
   params.fb_width   = av_info->geometry.max_width;
   params.fb_height  = av_info->geometry.max_height;
   params.channels   = 2;
   params.filename   = recording_file;
   params.fps        = av_info->timing.fps;
   params.samplerate = av_info->timing.sample_rate;
   params.pix_fmt    = (video_driver_get_pixel_format() == RETRO_PIXEL_FORMAT_XRGB8888) ?
      FFEMU_PIX_ARGB8888 : FFEMU_PIX_RGB565;
   params.config     = NULL;
   
   if (*global->record.config)
      params.config = global->record.config;

   if (settings->video.gpu_record && driver->video->read_viewport)
   {
      struct video_viewport vp = {0};

      video_driver_viewport_info(&vp);

      if (!vp.width || !vp.height)
      {
         RARCH_ERR("Failed to get viewport information from video driver. "
               "Cannot start recording ...\n");
         return false;
      }

      params.out_width  = vp.width;
      params.out_height = vp.height;
      params.fb_width   = next_pow2(vp.width);
      params.fb_height  = next_pow2(vp.height);

      if (settings->video.force_aspect &&
            (video_driver_get_aspect_ratio() > 0.0f))
         params.aspect_ratio  = video_driver_get_aspect_ratio();
      else
         params.aspect_ratio  = (float)vp.width / vp.height;

      params.pix_fmt             = FFEMU_PIX_BGR24;
      global->record.gpu_width   = vp.width;
      global->record.gpu_height  = vp.height;

      RARCH_LOG("%s %u x %u\n", msg_hash_to_str(MSG_DETECTED_VIEWPORT_OF),
            vp.width, vp.height);

      global->record.gpu_buffer = (uint8_t*)malloc(vp.width * vp.height * 3);
      if (!global->record.gpu_buffer)
         return false;
   }
   else
   {
      if (global->record.width || global->record.height)
      {
         params.out_width  = global->record.width;
         params.out_height = global->record.height;
      }

      if (settings->video.force_aspect &&
            (video_driver_get_aspect_ratio() > 0.0f))
         params.aspect_ratio = video_driver_get_aspect_ratio();
      else
         params.aspect_ratio = (float)params.out_width / params.out_height;

      if (settings->video.post_filter_record && video_driver_frame_filter_alive())
      {
         unsigned max_width  = 0;
         unsigned max_height = 0;

         if (video_driver_frame_filter_is_32bit())
            params.pix_fmt = FFEMU_PIX_ARGB8888;
         else
            params.pix_fmt =  FFEMU_PIX_RGB565;

         rarch_softfilter_get_max_output_size(
               video_driver_frame_filter_get_ptr(),
               &max_width, &max_height);
         params.fb_width  = next_pow2(max_width);
         params.fb_height = next_pow2(max_height);
      }
   }

   RARCH_LOG("%s %s @ %ux%u. (FB size: %ux%u pix_fmt: %u)\n",
         msg_hash_to_str(MSG_RECORDING_TO),
         global->record.path,
         params.out_width, params.out_height,
         params.fb_width, params.fb_height,
         (unsigned)params.pix_fmt);

   if (!record_driver_init_first(&driver->recording, &driver->recording_data, &params))
   {
      RARCH_ERR("%s\n", msg_hash_to_str(MSG_FAILED_TO_START_RECORDING));
      event_command(EVENT_CMD_GPU_RECORD_DEINIT);

      return false;
   }

   return true;
}
Ejemplo n.º 16
0
static void init_video_filter(enum retro_pixel_format colfmt)
{
    unsigned width, height, pow2_x, pow2_y, maxsize;
    struct retro_game_geometry *geom = NULL;
    settings_t *settings             = config_get_ptr();
    struct retro_system_av_info *av_info =
        video_viewport_get_system_av_info();

    deinit_video_filter();

    if (!*settings->video.softfilter_plugin)
        return;

    /* Deprecated format. Gets pre-converted. */
    if (colfmt == RETRO_PIXEL_FORMAT_0RGB1555)
        colfmt = RETRO_PIXEL_FORMAT_RGB565;

    if (video_state.hw_render_callback.context_type)
    {
        RARCH_WARN("Cannot use CPU filters when hardware rendering is used.\n");
        return;
    }

    geom    = av_info ? (struct retro_game_geometry*)&av_info->geometry : NULL;
    width   = geom->max_width;
    height  = geom->max_height;

    video_state.filter.filter = rarch_softfilter_new(
                                    settings->video.softfilter_plugin,
                                    RARCH_SOFTFILTER_THREADS_AUTO, colfmt, width, height);

    if (!video_state.filter.filter)
    {
        RARCH_ERR("Failed to load filter.\n");
        return;
    }

    rarch_softfilter_get_max_output_size(video_state.filter.filter,
                                         &width, &height);

    pow2_x                    = next_pow2(width);
    pow2_y                    = next_pow2(height);
    maxsize                   = max(pow2_x, pow2_y);
    video_state.filter.scale  = maxsize / RARCH_SCALE_BASE;
    video_state.filter.out_rgb32 = rarch_softfilter_get_output_format(
                                       video_state.filter.filter) == RETRO_PIXEL_FORMAT_XRGB8888;

    video_state.filter.out_bpp = video_state.filter.out_rgb32 ?
                                 sizeof(uint32_t) : sizeof(uint16_t);

    /* TODO: Aligned output. */
    video_state.filter.buffer = malloc(width * height * video_state.filter.out_bpp);
    if (!video_state.filter.buffer)
        goto error;

    return;

error:
    RARCH_ERR("Softfilter initialization failed.\n");
    deinit_video_filter();
}
Ejemplo n.º 17
0
static void *alsa_qsa_init(const char *device,
      unsigned rate, unsigned latency)
{
   int err, card, dev, i;
   snd_pcm_channel_params_t params = {0};
   snd_pcm_channel_info_t pi;
   snd_pcm_channel_setup_t setup = {0};
   settings_t *settings = config_get_ptr();
   alsa_t *alsa = (alsa_t*)calloc(1, sizeof(alsa_t));
   if (!alsa)
      return NULL;

   (void)device;
   (void)rate;
   (void)latency;

   if ((err = snd_pcm_open_preferred(&alsa->pcm, &card, &dev,
               SND_PCM_OPEN_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Audio open error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if((err = snd_pcm_nonblock_mode(alsa->pcm, 1)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Can't set blocking mode: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&pi, 0, sizeof(pi));
   pi.channel = SND_PCM_CHANNEL_PLAYBACK;
   if ((err = snd_pcm_channel_info(alsa->pcm, &pi)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: snd_pcm_channel_info failed: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&params, 0, sizeof(params));

   params.channel = SND_PCM_CHANNEL_PLAYBACK;
   params.mode = SND_PCM_MODE_BLOCK;

   params.format.interleave = 1;
   params.format.format = SND_PCM_SFMT_S16_LE;
   params.format.rate = DEFAULT_RATE;
   params.format.voices = 2;

   params.start_mode = SND_PCM_START_FULL;
   params.stop_mode = SND_PCM_STOP_STOP;

   params.buf.block.frag_size = pi.max_fragment_size;
   params.buf.block.frags_min = 2;
   params.buf.block.frags_max = 8;

   RARCH_LOG("Fragment size: %d\n", params.buf.block.frag_size);
   RARCH_LOG("Min Fragment size: %d\n", params.buf.block.frags_min);
   RARCH_LOG("Max Fragment size: %d\n", params.buf.block.frags_max);

   if ((err = snd_pcm_channel_params(alsa->pcm, &params)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   setup.channel = SND_PCM_CHANNEL_PLAYBACK;

   if ((err = snd_pcm_channel_setup(alsa->pcm, &setup)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Read Back Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if (settings->audio.block_frames)
      alsa->buf_size = settings->audio.block_frames * 4;
   else
      alsa->buf_size = next_pow2(32 * latency);

   RARCH_LOG("[ALSA QSA]: buffer size: %u bytes\n", alsa->buf_size);

   alsa->buf_count = (latency * 4 * rate + 500) / 1000;
   alsa->buf_count = (alsa->buf_count + alsa->buf_size / 2) / alsa->buf_size;

   if ((err = snd_pcm_channel_prepare(alsa->pcm,
               SND_PCM_CHANNEL_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Prepare Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   alsa->buffer = (uint8_t**)calloc(sizeof(uint8_t*), alsa->buf_count);
   if (!alsa->buffer)
      goto error;

   alsa->buffer_chunk = (uint8_t*)calloc(alsa->buf_count, alsa->buf_size);
   if (!alsa->buffer_chunk)
      goto error;

   for (i = 0; i < alsa->buf_count; i++)
      alsa->buffer[i] = alsa->buffer_chunk + i * alsa->buf_size;

   alsa->has_float = false;
   alsa->can_pause = true;
   RARCH_LOG("[ALSA QSA]: Can pause: %s.\n",
         alsa->can_pause ? "yes" : "no");

   return alsa;

error:
   return (void*)-1;
}
Ejemplo n.º 18
0
void init_video(void)
{
    unsigned max_dim, scale, width, height;
    video_viewport_t *custom_vp      = NULL;
    const input_driver_t *tmp        = NULL;
    const struct retro_game_geometry *geom = NULL;
    video_info_t video               = {0};
    static uint16_t dummy_pixels[32] = {0};
    driver_t *driver                 = driver_get_ptr();
    settings_t *settings             = config_get_ptr();
    rarch_system_info_t *system      = rarch_system_info_get_ptr();
    struct retro_system_av_info *av_info =
        video_viewport_get_system_av_info();

    init_video_filter(video_state.pix_fmt);
    event_command(EVENT_CMD_SHADER_DIR_INIT);

    if (av_info)
        geom      = (const struct retro_game_geometry*)&av_info->geometry;
    max_dim   = max(geom->max_width, geom->max_height);
    scale     = next_pow2(max_dim) / RARCH_SCALE_BASE;
    scale     = max(scale, 1);

    if (video_state.filter.filter)
        scale = video_state.filter.scale;

    /* Update core-dependent aspect ratio values. */
    video_viewport_set_square_pixel(geom->base_width, geom->base_height);
    video_viewport_set_core();
    video_viewport_set_config();

    /* Update CUSTOM viewport. */
    custom_vp = video_viewport_get_custom();

    if (settings->video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
    {
        float default_aspect = aspectratio_lut[ASPECT_RATIO_CORE].value;
        aspectratio_lut[ASPECT_RATIO_CUSTOM].value =
            (custom_vp->width && custom_vp->height) ?
            (float)custom_vp->width / custom_vp->height : default_aspect;
    }

    video_driver_set_aspect_ratio_value(
        aspectratio_lut[settings->video.aspect_ratio_idx].value);

    if (settings->video.fullscreen)
    {
        width  = settings->video.fullscreen_x;
        height = settings->video.fullscreen_y;
    }
    else
    {
        if (settings->video.force_aspect)
        {
            /* Do rounding here to simplify integer scale correctness. */
            unsigned base_width =
                roundf(geom->base_height * video_driver_get_aspect_ratio());
            width  = roundf(base_width * settings->video.scale);
        }
        else
            width  = roundf(geom->base_width   * settings->video.scale);
        height = roundf(geom->base_height * settings->video.scale);
    }

    if (width && height)
        RARCH_LOG("Video @ %ux%u\n", width, height);
    else
        RARCH_LOG("Video @ fullscreen\n");

    driver->display_type  = RARCH_DISPLAY_NONE;
    driver->video_display = 0;
    driver->video_window  = 0;

    if (!init_video_pixel_converter(RARCH_SCALE_BASE * scale))
    {
        RARCH_ERR("Failed to initialize pixel converter.\n");
        rarch_fail(1, "init_video()");
    }

    video.width        = width;
    video.height       = height;
    video.fullscreen   = settings->video.fullscreen;
    video.vsync        = settings->video.vsync && !system->force_nonblock;
    video.force_aspect = settings->video.force_aspect;
#ifdef GEKKO
    video.viwidth      = settings->video.viwidth;
    video.vfilter      = settings->video.vfilter;
#endif
    video.smooth       = settings->video.smooth;
    video.input_scale  = scale;
    video.rgb32        = video_state.filter.filter ?
                         video_state.filter.out_rgb32 :
                         (video_state.pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);

    tmp = (const input_driver_t*)driver->input;
    /* Need to grab the "real" video driver interface on a reinit. */
    find_video_driver();

#ifdef HAVE_THREADS
    if (settings->video.threaded && !video_state.hw_render_callback.context_type)
    {
        /* Can't do hardware rendering with threaded driver currently. */
        RARCH_LOG("Starting threaded video driver ...\n");

        if (!rarch_threaded_video_init(&driver->video, &driver->video_data,
                                       &driver->input, &driver->input_data,
                                       driver->video, &video))
        {
            RARCH_ERR("Cannot open threaded video driver ... Exiting ...\n");
            rarch_fail(1, "init_video()");
        }
    }
    else
#endif
        driver->video_data = driver->video->init(&video, &driver->input,
                             &driver->input_data);

    if (!driver->video_data)
    {
        RARCH_ERR("Cannot open video driver ... Exiting ...\n");
        rarch_fail(1, "init_video()");
    }

    driver->video_poke = NULL;
    if (driver->video->poke_interface)
        driver->video->poke_interface(driver->video_data, &driver->video_poke);

    if (driver->video->viewport_info && (!custom_vp->width ||
                                         !custom_vp->height))
    {
        /* Force custom viewport to have sane parameters. */
        custom_vp->width = width;
        custom_vp->height = height;
        video_driver_viewport_info(custom_vp);
    }

    video_driver_set_rotation(
        (settings->video.rotation + system->rotation) % 4);

    video_driver_suppress_screensaver(settings->ui.suspend_screensaver_enable);

    if (!driver->input)
        init_video_input(tmp);

    event_command(EVENT_CMD_OVERLAY_DEINIT);
    event_command(EVENT_CMD_OVERLAY_INIT);

    video_driver_cached_frame_set(&dummy_pixels, 4, 4, 8);

#if defined(PSP)
    video_driver_set_texture_frame(&dummy_pixels, false, 1, 1, 1.0f);
#endif
}
Ejemplo n.º 19
0
bool d3d_init_chain(void *data, const video_info_t *video_info)
{
   D3DVideo *d3d = reinterpret_cast<D3DVideo*>(data);
   // Setup information for first pass.
   LinkInfo link_info = {0};

   link_info.pass = &d3d->shader.pass[0];
   link_info.tex_w = link_info.tex_h = video_info->input_scale * RARCH_SCALE_BASE;

   delete d3d->chain;
   d3d->chain = new RenderChain(
         &d3d->video_info,
         d3d->dev, d3d->cgCtx,
         d3d->final_viewport);

   if (!d3d->chain->init(link_info,
            d3d->video_info.rgb32 ? RenderChain::ARGB : RenderChain::RGB565))
   {
      RARCH_ERR("[D3D9]: Failed to init render chain.\n");
      return false;
   }

   unsigned current_width = link_info.tex_w;
   unsigned current_height = link_info.tex_h;
   unsigned out_width = 0;
   unsigned out_height = 0;

   for (unsigned i = 1; i < d3d->shader.passes; i++)
   {
      RenderChain::convert_geometry(link_info,
            out_width, out_height,
            current_width, current_height, d3d->final_viewport);

      link_info.pass = &d3d->shader.pass[i];
      link_info.tex_w = next_pow2(out_width);
      link_info.tex_h = next_pow2(out_height);

      current_width = out_width;
      current_height = out_height;

      if (!d3d->chain->add_pass(link_info))
      {
         RARCH_ERR("[D3D9]: Failed to add pass.\n");
         return false;
      }
   }

   if (!d3d_init_luts(d3d))
   {
      RARCH_ERR("[D3D9]: Failed to init LUTs.\n");
      return false;
   }

   if (!d3d_init_imports(d3d))
   {
      RARCH_ERR("[D3D9]: Failed to init imports.\n");
      return false;
   }

   return true;
}
Ejemplo n.º 20
0
static bool is_pow2(int x) { return x == next_pow2(x); }