Exemple #1
0
void fs_emu_draw_from_atlas(float dx, float dy, float dw, float dh,
        int sx, int sy, int sw, int sh) {
    float tx = sx / 1024.0;
    float ty = sy / 1024.0;
    float tw = sw / 1024.0;
    float th = sh / 1024.0;
    //fs_gl_texturing(1);
    //fs_gl_bind_texture(g_atlas->texture);
    //printf("%f %f %f %f - %f %f %f %f\n", dx, dy, dw, dh, tx, ty, tw, th);

    fs_emu_set_texture(g_atlas);
    GLfloat tex[] = {
        tx, ty + th,
        tx + tw, ty + th,
        tx + tw, ty,
        tx, ty
    };
    GLfloat vert[] = {
        dx, dy,
        dx + dw, dy,
        dx + dw, dy + dh,
        dx, dy + dh
    };
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(2, GL_FLOAT, 0, vert);
    glTexCoordPointer(2, GL_FLOAT, 0, tex);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    CHECK_GL_ERROR();
}
Exemple #2
0
void fs_emu_render_texture_with_size(fs_emu_texture *texture, int x, int y,
        int w, int h) {
    fs_emu_set_texture(texture);
    fs_gl_blending(1);
    //fs_emu_texturing(0);
    //return;
    //fs_log("%d %d %d %d\n", x, y, x + w , y + h);
    GLfloat tex[] = {
        0.0, 1.0,
        1.0, 1.0,
        1.0, 1.0,
        1.0, 0.0
    };
    GLfloat vert[] = {
        x, y,
        x + w, y,
        x + w, y + h,
        x, y + h
    };
    
    glColor4f(1.0, 1.0, 1.0, 1.0);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    glVertexPointer(2, GL_FLOAT, 0, vert);
    glTexCoordPointer(2, GL_FLOAT, 0, tex);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    CHECK_GL_ERROR();
}
Exemple #3
0
void fs_emu_prepare_texture(int entry, float *tx1, float *ty1,
        float *tx2, float *ty2) {
    *tx1 = g_entries[entry].x / 1024.0;
    *ty1 = g_entries[entry].y / 1024.0;
    *tx2 = *tx1 + g_entries[entry].w / 1024.0;
    *ty2 = *ty1 + g_entries[entry].h / 1024.0;
    fs_emu_set_texture(g_atlas);
}
Exemple #4
0
void fs_emu_video_render_function() {
    static int initialized_menu = 0;
    if (!initialized_menu) {
        // render menu once (without really showing it, so all menu
        // resources are initialized and loaded, -prevents flickering
        // when really opening the menu later
        fs_emu_render_menu(g_menu_transition);
        initialized_menu = 1;
    }

    if (g_fs_emu_video_debug) {
        int quarter_height = fs_ml_video_height() / 4;
        fs_gl_viewport(0, quarter_height, fs_ml_video_width(),
                fs_ml_video_height() - quarter_height);
    }
    else {
        fs_gl_viewport(0, 0, fs_ml_video_width(), fs_ml_video_height());
    }

    // FIXME: can perhaps remove this soon..
    fs_emu_video_render_mutex_lock();

    int in_menu = fs_emu_menu_is_active();
    if (in_menu && g_menu_transition_target < 1.0) {
        g_menu_transition_target = 1.0;
    }
    if (!in_menu && g_menu_transition_target > 0.0) {
        g_menu_transition_target = 0.0;
    }

    // FIXME: ideally, we would use time-based animation - for now, we use a
    // simple frame-based animation
    if (g_menu_transition < g_menu_transition_target) {
        if (g_menu_transition_target == 1.0) {
            g_menu_transition += 0.10;
        }
    }
    if (g_menu_transition > g_menu_transition_target) {
        if (g_menu_transition_target == 0.0) {
            g_menu_transition -= 0.10;
        }
    }
    if (g_menu_transition > 1.0) {
        g_menu_transition = 1.0;
    }
    else if (g_menu_transition < 0.0) {
        g_menu_transition = 0.0;
    }

    int matrix_pushed = 0;

    double t0_x = 0.0;
    double t0_y = 0.0;
    double t0_z = -2.42;
    double r0_a = 0.0;

    double t1_x = -0.31;
    //double t1_y = -0.04;
    double t1_y = 0.0;
    double t1_z = -3.7;
    double r1_a = 30.0;

    int perspective = 0;
    if (g_menu_transition == 0.0) {
        perspective = 0;
        fs_gl_ortho();
        //glTranslated(1920.0 / 2.0, 1080.0 / 2.0, 0.0);
        //glScaled(1920.0 / 2.0, 1080.0 / 2.0, 1.0);
    }
    else {
        perspective = 1;

        glClearColor(0.1, 0.1, 0.1, 1.0);
        glClear(GL_DEPTH_BUFFER_BIT);
        CHECK_GL_ERROR();
        fs_gl_ortho_hd();

        // transition y-coordinate between floor and wall
        int splt = 361;
        fs_gl_blending(FALSE);
        fs_gl_texturing(FALSE);
        GLfloat color[] = {
            39.0 / 255.0, 44.0 / 255.0, 51.0 / 255.0, 1.0,
            39.0 / 255.0, 44.0 / 255.0, 51.0 / 255.0, 1.0,
            0.0, 0.0, 0.0, 1.0,
            0.0, 0.0, 0.0, 1.0,

            0.0, 0.0, 0.0, 1.0,
            0.0, 0.0, 0.0, 1.0,
            0.0, 0.0, 0.0, 1.0,
            0.0, 0.0, 0.0, 1.0,

            0.0, 0.0, 0.0, 1.0,
            0.0, 0.0, 0.0, 1.0,
            20.0 / 255.0, 22.0 / 255.0, 26.0 / 255.0, 1.0,
            20.0 / 255.0, 22.0 / 255.0, 26.0 / 255.0, 1.0
        };
        GLfloat vert[] = {
               0, splt, -0.9,
            1920, splt, -0.9,
            1920, 1020, -0.9,
               0, 1020, -0.9,

               0, 1020, -0.9,
            1920, 1020, -0.9,
            1920, 1080, -0.9,
               0, 1080, -0.9,

               0,    0, -0.9,
            1920,    0, -0.9,
            1920, splt, -0.9,
               0, splt, -0.9
        };

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);

        glColorPointer(4, GL_FLOAT, 0, color);
        glVertexPointer(3, GL_FLOAT, 0, vert);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 12);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
        CHECK_GL_ERROR();

        fs_gl_perspective();
        double t_x = t0_x + (t1_x - t0_x) * g_menu_transition;
        double t_y = t0_y + (t1_y - t0_y) * g_menu_transition;
        double t_z = t0_z + (t1_z - t0_z) * g_menu_transition;
        double r_a = r0_a + (r1_a - r0_a) * g_menu_transition;

        glPushMatrix();
        matrix_pushed = 1;

        glScaled(16.0 / 9.0, 1.0, 1.0);
        glTranslated(t_x, t_y, t_z);
        glRotated(r_a, 0.0, 1.0, 0.0);
        CHECK_GL_ERROR();
    }

    if (perspective) {
        render_glow(g_menu_transition);
    }
    if (perspective) {
        glPushMatrix();
        glTranslatef(0.0, -2.0, 0.0);
        //glTranslatef(0.0, -1.0, 0.0);
        //glScalef(1.0, -1.0, 1.0);
        glScalef(1.0, -0.5, 1.0);
        glTranslatef(0.0, -1.0, 0.0);
        CHECK_GL_ERROR();
        render_frame(0.33, perspective);
        CHECK_GL_ERROR();
        render_gloss(g_menu_transition * 0.66);
        CHECK_GL_ERROR();
        glPopMatrix();
        CHECK_GL_ERROR();
    }
    render_frame(1.0, perspective);
    if (perspective) {
        render_gloss(g_menu_transition);
    }
    /*
    if (fs_emu_is_paused()) {
        render_pause_fade();
    }
    */

    if (matrix_pushed) {
        glPopMatrix();
        CHECK_GL_ERROR();
        matrix_pushed = 0;
    }

    fs_emu_acquire_gui_lock();
    fs_emu_render_chat();

    //if (fs_emu_menu_is_active()) {
    if (g_menu_transition > 0.0) {
        fs_emu_render_menu(g_menu_transition);
    }

	fs_emu_render_dialog();
    fs_emu_release_gui_lock();

    if (g_fs_emu_hud_mode && fs_emu_netplay_enabled()) {
        fs_gl_ortho_hd();
        fs_gl_texturing(0);
        fs_gl_blending(1);
	fs_gl_color4f(0.0, 0.0, 0.0, 0.5);
        GLfloat vert[] = {
            0, 1030,
            1920, 1030,
            1920, 1080,
            0, 1080
        };
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(2, GL_FLOAT, 0, vert);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        glDisableClientState(GL_VERTEX_ARRAY);
        CHECK_GL_ERROR();
#if 0
        glBegin(GL_QUADS);
        glVertex2f(0, 1030);
        glVertex2f(1920, 1030);
        fs_gl_color4f(0.0, 0.0, 0.0, 0.0);
        glVertex2f(1920, 1030 - 50);
        glVertex2f(0, 1030 - 50);
        glEnd();
#endif
        fs_emu_font *menu_font = fs_emu_font_get_menu();
        char *str;

        for (int i = 0; i < MAX_PLAYERS; i++) {
            fs_emu_player *player = g_fs_emu_players + i;
            int x = i * 1920 / 6 + 20;
            int y = 1038;

            int rendered_tag = 0;
            if (player->tag && player->tag[0]) {
                str = g_strdup_printf("%s", player->tag);
                fs_emu_font_render(menu_font, str, x, y,
                        1.0, 1.0, 1.0, 1.0);
                g_free(str);
                rendered_tag = 1;
            }
            if (rendered_tag || player->ping) {
                str = g_strdup_printf("%03d", player->ping);
                fs_emu_font_render(menu_font, str, x + 100, y,
                        1.0, 1.0, 1.0, 1.0);
                g_free(str);
            }
            if (rendered_tag || player->lag) {
                str = g_strdup_printf("%03d", player->lag);
                fs_emu_font_render(menu_font, str, x + 200, y,
                        1.0, 1.0, 1.0, 1.0);
                g_free(str);
            }
        }
    }

    if (g_fs_emu_video_debug) {
        int quarter_height = fs_ml_video_height() / 4;
        fs_gl_viewport(0, 0, fs_ml_video_width(), quarter_height);
        CHECK_GL_ERROR();

        fs_emu_set_texture(NULL);
        CHECK_GL_ERROR();
        static GLuint debug_texture = 0;
        static uint32_t *debug_texture_data = NULL;
        if (debug_texture == 0) {
            debug_texture_data = g_malloc0(256 * 256 * 4);
            glGenTextures(1, &debug_texture);
            CHECK_GL_ERROR();
            fs_gl_bind_texture(debug_texture);
#ifndef HAVE_GLES
            fs_gl_unpack_row_length(0);
#endif
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
                    GL_RGBA, GL_UNSIGNED_BYTE, NULL);
            CHECK_GL_ERROR();
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
                    GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
                    GL_CLAMP_TO_EDGE);
            CHECK_GL_ERROR();
        }
        else {
            fs_gl_bind_texture(debug_texture);
            CHECK_GL_ERROR();
        }

        memset(debug_texture_data, 0x00, 256 * 256 * 4);
        CHECK_GL_ERROR();
        fs_emu_video_render_debug_info(debug_texture_data);
        CHECK_GL_ERROR();
        fs_emu_audio_render_debug_info(debug_texture_data);
        CHECK_GL_ERROR();

#ifndef HAVE_GLES
        fs_gl_unpack_row_length(0);
#endif
        CHECK_GL_ERROR();
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 256,
                GL_RGBA, GL_UNSIGNED_BYTE, debug_texture_data);
        CHECK_GL_ERROR();
        fs_gl_ortho_hd();
        fs_gl_texturing(1);
        fs_gl_blending(0);
        fs_gl_color4f(1.0, 1.0, 1.0, 1.0);
        GLfloat tex[] = {
            0.0, 0.0,
            1.0, 0.0,
            1.0, 1.0,
            0.0, 1.0
        };
        GLfloat vert[] = {
            0, 0,
            1920, 0,
            1920, 1080,
            0, 1080
        };

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glTexCoordPointer(2, GL_FLOAT, 0, tex);
        glVertexPointer(2, GL_FLOAT, 0, vert);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        CHECK_GL_ERROR();

        glPushMatrix();
        glScalef(1.0, 4.0, 1.0);

        fs_emu_font *menu_font = fs_emu_font_get_menu();
        char *str;

        /*
        str = g_strdup_printf("%d", fs_emu_get_audio_frequency());
        fs_emu_font_render(menu_font, str, 1920 / 2 + 20, 3,
                1.0, 1.0, 1.0, 1.0);
        g_free(str);
        */

        str = g_strdup_printf("%0.1f",
                fs_emu_audio_get_measured_avg_buffer_fill(0) / 1000.0);
        fs_emu_font_render(menu_font, str, 1920 / 2 + 220, 3,
                1.0, 1.0, 1.0, 1.0);
        g_free(str);
        str = g_strdup_printf("%d", g_fs_emu_audio_buffer_underruns);
        fs_emu_font_render(menu_font, str, 1920 / 2 + 420, 3,
                1.0, 1.0, 1.0, 1.0);
        g_free(str);

        fs_emu_font_render(menu_font, "EMU", 20, 3, 1.0, 1.0, 1.0, 1.0);
        str = g_strdup_printf("%0.1f", fs_emu_get_average_emu_fps());
        fs_emu_font_render(menu_font, str, 220, 3, 1.0, 1.0, 1.0, 1.0);
        g_free(str);
        str = g_strdup_printf("%d", g_fs_emu_lost_frames);
        fs_emu_font_render(menu_font, str, 420, 3, 1.0, 1.0, 1.0, 1.0);
        g_free(str);
        str = g_strdup_printf("%d", g_fs_emu_repeated_frames);
        fs_emu_font_render(menu_font, str, 620, 3, 1.0, 1.0, 1.0, 1.0);
        g_free(str);

        fs_emu_font_render(menu_font, "SYS", 20, 140, 1.0, 1.0, 1.0, 1.0);
        str = g_strdup_printf("%0.1f", fs_emu_get_average_sys_fps());
        fs_emu_font_render(menu_font, str, 220, 140, 1.0, 1.0, 1.0, 1.0);
        g_free(str);
        str = g_strdup_printf("%d", g_fs_emu_lost_vblanks);
        fs_emu_font_render(menu_font, str, 420, 140, 1.0, 1.0, 1.0, 1.0);
        g_free(str);

        glPopMatrix();
        CHECK_GL_ERROR();
    }

    if (fs_emu_is_quitting()) {
        handle_quit_sequence();
    }

    fs_emu_video_render_mutex_unlock();
}
Exemple #5
0
fs_emu_texture *fs_emu_texture_new_from_file(const char *name) {
    char *full_name;
    char *path;
    if (fs_path_exists(name)) {
        full_name = fs_strdup(name);
        path = fs_strdup(name);
    }
    else {
        full_name = fs_strconcat(name, ".png", NULL);
        path = fs_get_program_data_file(full_name);
        if (path == NULL) {
            fs_emu_warning("Could not find texture %s\n", full_name);
            return NULL;
        }
    }
    fs_image *image = fs_image_new_from_file(path);
    fs_emu_log("loading texture \"%s\"\n", path);
    free(path);
    if (image == NULL) {
        fs_emu_warning("Could not load texture from %s\n", full_name);
        free(full_name);
        return NULL;
    }
    free(full_name);

    if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) {
        // convert to premultiplied alpha
        if (image->format == FS_IMAGE_FORMAT_RGBA) {
            int num_pixels = image->width * image->height;
            unsigned char *pixels = image->data;
            for (int i = 0; i < num_pixels; i++) {
                unsigned char alpha = pixels[3];
                unsigned char temp = pixels[2];
                pixels[2] = ((int) pixels[0]) * alpha / 255;
                pixels[1] = ((int) pixels[1]) * alpha / 255;
                pixels[0] = ((int) temp) * alpha / 255;
                pixels += 4;
            }
        }
        else {
            // FIXME: should swap R and B here...
        }
    }
    else {
        // convert to premultiplied alpha
        if (image->format == FS_IMAGE_FORMAT_RGBA) {
            int num_pixels = image->width * image->height;
            unsigned char *pixels = image->data;
            for (int i = 0; i < num_pixels; i++) {
                unsigned char alpha = pixels[3];
                // should really divide by 255, but 256 is faster...
                //pixels[0] = ((int) pixels[0]) * alpha / 256;
                //pixels[1] = ((int) pixels[1]) * alpha / 256;
                //pixels[2] = ((int) pixels[2]) * alpha / 256;
                pixels[0] = ((int) pixels[0]) * alpha / 255;
                pixels[1] = ((int) pixels[1]) * alpha / 255;
                pixels[2] = ((int) pixels[2]) * alpha / 255;
                //pixels[0] = (unsigned char) ((pixels[0] * alpha + 0.5) / 255.0);
                //pixels[1] = (unsigned char) ((pixels[1] * alpha + 0.5) / 255.0);
                //pixels[2] = (unsigned char) ((pixels[2] * alpha + 0.5) / 255.0);
                pixels += 4;
            }
        }
    }

    fs_emu_texture *texture = fs_new(fs_emu_texture, 1);
    texture->width = image->width;
    texture->height = image->height;
    texture->image = image;
    load_texture(texture);
    fs_emu_set_texture(texture);

    fs_gl_add_context_notification(context_notification_handler, texture);

    return texture;
}
Exemple #6
0
void fs_emu_initialize_textures() {
    if (g_fs_emu_theme.width == 0) {
        fs_emu_fatal("theme is not initialized yet");
    }

    //g_atlas = fs_emu_texture_new_from_file("atlas");
    fs_image *image = fs_image_new();
    image->width = 1024;
    image->height = 1024;
    image->format = FS_IMAGE_FORMAT_RGBA;
    image->data = fs_malloc0(1024 * 1024 * 4);
    initialize_atlas(image);

    g_atlas = fs_new(fs_emu_texture, 1);
    g_atlas->width = image->width;
    g_atlas->height = image->height;
    g_atlas->image = image;
    load_texture(g_atlas);
    fs_emu_set_texture(g_atlas);
    fs_gl_add_context_notification(context_notification_handler, g_atlas);

    if (g_fs_emu_theme.overlay_image[0]) {
        char *path = fs_emu_theme_get_resource(g_fs_emu_theme.overlay_image);
        fs_log("g_fs_emu_theme.overlay_image %s => %s\n",
                g_fs_emu_theme.overlay_image, path);
        if (path) {
            g_fs_emu_overlay_texture = fs_emu_texture_new_from_file(path);
        }
    }

    for (int i = 0; i < FS_EMU_MAX_OVERLAYS; i++) {
        for (int j = 0; j < FS_EMU_MAX_OVERLAY_STATES; j++) {
            fs_emu_texture *tex = NULL;
            char *name = fs_strdup_printf("custom_%d_%d.png",
                    i - FS_EMU_FIRST_CUSTOM_OVERLAY, j);
            char *path = fs_emu_theme_get_resource(name);
            if (!path && g_fs_emu_theme.overlays[i].name) {
                free(name);
                name = fs_strdup_printf("%s_%d.png",
                        g_fs_emu_theme.overlays[i].name, j);
                path = fs_emu_theme_get_resource(name);
            }
            if (path) {
                tex = fs_emu_texture_new_from_file(path);
                g_fs_emu_theme.overlays[i].textures[j] = tex;
                free(path);
            }
            else if (j == 1) {
                char *base_name = fs_strdup_printf("custom_%d.png",
                        i - FS_EMU_FIRST_CUSTOM_OVERLAY);
                path = fs_emu_theme_get_resource(base_name);
                if (!path && g_fs_emu_theme.overlays[i].name) {
                    free(name);
                    name = fs_strdup_printf("%s.png",
                            g_fs_emu_theme.overlays[i].name);
                    path = fs_emu_theme_get_resource(name);
                }
                if (path) {
                    tex = fs_emu_texture_new_from_file(path);
                    g_fs_emu_theme.overlays[i].textures[j] = tex;
                    free(path);
                }
                free(base_name);
            }
            else if (j >= 2) {
                g_fs_emu_theme.overlays[i].textures[j] = \
                        g_fs_emu_theme.overlays[i].textures[j - 1];
            }
            free(name);

            // size will be determined from the last loaded texture/state
            // for the overlay
            if (tex) {
                g_fs_emu_theme.overlays[i].w =
                        (double) tex->width / g_fs_emu_theme.width;
                g_fs_emu_theme.overlays[i].h =
                        (double) tex->height / g_fs_emu_theme.height;
            }
        }
    }
}