Beispiel #1
0
static void unqueue_old_buffers(int stream)
{
    audio_stream *s = g_streams[stream];
    ALint old_buffers = 0;
    fs_mutex_lock(s->mutex);
    // locking here because unqueue_old_buffers can be run called from
    // both the video thread and the emulation thread (consider changing this,
    // perhaps even have a separate thread for periodically unqueuing).
    alGetSourcei(s->source, AL_BUFFERS_PROCESSED, &old_buffers);
    check_al_error("alGetSourcei (AL_BUFFERS_PROCESSED)");

    if (old_buffers > 0) {
        ALuint buffers[MAX_BUFFERS];
        old_buffers = MIN(old_buffers, MAX_BUFFERS);
        alSourceUnqueueBuffers(s->source, old_buffers, buffers);
        if (check_al_error("alSourceUnqueueBuffers") != AL_NO_ERROR) {
            fs_log("while trying to unqueue %d buffers\n");
        }
        for (int i = 0; i < old_buffers; i++) {
            g_queue_push_tail(s->queue, FS_UINT_TO_POINTER(buffers[i]));
        }
        s->buffers_queued -= old_buffers;
    }
    fs_mutex_unlock(s->mutex);
}
Beispiel #2
0
static void fs_emu_init_audio_stream(int stream,
                              fs_emu_audio_stream_options *options)
{
    audio_stream *s = g_malloc0(sizeof(audio_stream));
    s->buffer_size = options->buffer_size;
    s->frequency = options->frequency;
    s->num_buffers = MAX_BUFFERS;
    s->min_buffers = options->min_buffers;
    fs_log("AUDIO: Stream %d,  frequency: %d, buffers: %d buffer "
           "size: %d bytes\n", stream, s->frequency, s->num_buffers,
           s->buffer_size);
    s->mutex = fs_mutex_create();
    s->queue = g_queue_new();
    s->source_volume_current = 1.0;
    s->buffers_queued = 0;
    s->pid_last_error = 0;
    s->pid_last_last_error = 0;
    s->pid_last_time = 0;
    s->pid_last_last_time = 0;

    alGenSources(1, &s->source);
    //alSourcei (s->source, AL_SOURCE_RELATIVE, AL_TRUE);
    //alSource3f(s->source, AL_POSITION, 0.0, 0.0, -1.0);
    //alSourcef (s->source, AL_ROLLOFF_FACTOR, 0.0);
    // AL_DIRECT_CHANNELS_SOFT
    alSourcei(s->source, 0x1033, AL_TRUE);

    check_al_error("alGenSources");
    for (int i = 0; i < s->num_buffers; i++) {
        ALuint buffer;
        alGenBuffers(1, &buffer);
        check_al_error("alGenBuffers");
        g_queue_push_tail(s->queue, FS_UINT_TO_POINTER(buffer));
    }

    if (stream == 0) {
        s->fill_target = g_default_fill_target;
    } else {
        s->fill_target = 0;
    }

    g_streams[stream] = s;
}
Beispiel #3
0
static void handle_element(parse_data *data, const char *element,
        const char *text) {
    if (data->error) {
        return;
    }
    //int node = 0;
    int vertex_shader = 0;
    //int fragment_shader = 0;
    if (strcmp(element, "vertex") == 0) {
        vertex_shader = 1;
    }
    else if (strcmp(element, "fragment") == 0) {
        //fragment_shader = 1;
    }
    else {
        // If the element's name is not vertex or fragment, end this
        // iteration of the loop and go immediately to the next iteration.
        return;
    }
    if (vertex_shader) {
        if (data->shader->current_shaders != NULL) {
            // If "the current list of shaders" is not empty, this shader
            // file is invalid. Abort this algorithm, do not continue
            // trying to load the file. Host applications should alert
            // the user that there was a problem loading the shader.
            fs_emu_warning("Error (1) loading shader");
            data->error = 1;
            return;
        }

        // Take the text content of this element, compile it as a vertex
        // shader.

        const GLchar *source = data->buffer;
        GLuint shader = glCreateShader(GL_VERTEX_SHADER);
        CHECK_GL_ERROR();
        glShaderSource(shader, 1, &source, NULL);
        CHECK_GL_ERROR();
        glCompileShader(shader);
        CHECK_GL_ERROR();

        // Check the compilation status of the new shader. If compilation
        // failed, this shader file is invalid. Abort this algorithm, do not
        // continue trying to load the file. Host applications should alert the
        // user that there was a problem loading the file.

        GLint compile_status;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
        CHECK_GL_ERROR();
        log_shader_log(shader);
        if (compile_status == GL_FALSE) {
            fs_emu_warning("failed to compile vertex shader");
            data->error = 1;
            return;
        }
        else {
            fs_log("compiled vertex shader successfully\n");
        }
        data->shader->current_shaders = g_list_append(
                data->shader->current_shaders,
                FS_UINT_TO_POINTER(shader));
        return;
    }
    // If the element has more than one attribute from the set
    // {size, size_x, scale, scale_x, outscale, outscale_x}, this shader file
    // is invalid. Abort this algorithm, do not continue trying to load the
    // file. Host applications should alert the user that there was a
    // problem loading the file.
    int count = 0;
    if (HASATTR(SIZE)) count++;
    if (HASATTR(SIZE_X)) count++;
    if (HASATTR(SCALE)) count++;
    if (HASATTR(SCALE_X)) count++;
    if (HASATTR(OUTSCALE)) count++;
    if (HASATTR(OUTSCALE_X)) count++;
    if (count > 1) {
        fs_emu_warning("Error (3) loading shader");
        data->error = 1;
        return;
    }

    // If the element has more than one attribute from the set
    // {size, size_y, scale, scale_y, outscale, outscale_y}, this shader file
    // is invalid. Abort this algorithm, do not continue trying to load the
    // file. Host applications should alert the user that there was a
    // problem loading the file.
    count = 0;
    if (HASATTR(SIZE)) count++;
    if (HASATTR(SIZE_Y)) count++;
    if (HASATTR(SCALE)) count++;
    if (HASATTR(SCALE_Y)) count++;
    if (HASATTR(OUTSCALE)) count++;
    if (HASATTR(OUTSCALE_Y)) count++;
    if (count > 1) {
        fs_emu_warning("Error (4) loading shader");
        data->error = 1;
        return;
    }

    int cur_hor_scale_method = SCALING_NOTSET;
    float cur_hor_scale_value = 0;
    if (HASATTR(SIZE)) {
        cur_hor_scale_method = SCALING_FIXED;
        cur_hor_scale_value = data->size;
    }
    else if (HASATTR(SIZE_X)) {
        cur_hor_scale_method = SCALING_FIXED;
        cur_hor_scale_value = data->size_x;
    }
    else if (HASATTR(SCALE)) {
        cur_hor_scale_method = SCALING_INPUT;
        cur_hor_scale_value = data->scale;
    }
    else if (HASATTR(SCALE_X)) {
        cur_hor_scale_method = SCALING_INPUT;
        cur_hor_scale_value = data->scale_x;
    }
    else if (HASATTR(OUTSCALE)) {
        cur_hor_scale_method = SCALING_OUTPUT;
        cur_hor_scale_value = data->outscale;
    }
    else if (HASATTR(OUTSCALE_X)) {
        cur_hor_scale_method = SCALING_OUTPUT;
        cur_hor_scale_value = data->outscale_x;
    }

    int cur_ver_scale_method = SCALING_NOTSET;
    float cur_ver_scale_value = 0;
    if (HASATTR(SIZE)) {
        cur_ver_scale_method = SCALING_FIXED;
        cur_ver_scale_value = data->size;
    }
    else if (HASATTR(SIZE_Y)) {
        cur_ver_scale_method = SCALING_FIXED;
        cur_ver_scale_value = data->size_y;
    }
    else if (HASATTR(SCALE)) {
        cur_ver_scale_method = SCALING_INPUT;
        cur_ver_scale_value = data->scale;
    }
    else if (HASATTR(SCALE_Y)) {
        cur_ver_scale_method = SCALING_INPUT;
        cur_ver_scale_value = data->scale_y;
    }
    else if (HASATTR(OUTSCALE)) {
        cur_ver_scale_method = SCALING_OUTPUT;
        cur_ver_scale_value = data->outscale;
    }
    else if (HASATTR(OUTSCALE_Y)) {
        cur_ver_scale_method = SCALING_OUTPUT;
        cur_ver_scale_value = data->outscale_y;
    }

    // Take the text content of this element, compile it as a fragment shader

    const GLchar *source = data->buffer;
    GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
    CHECK_GL_ERROR();
    glShaderSource(shader, 1, &source, NULL);
    CHECK_GL_ERROR();
    glCompileShader(shader);
    CHECK_GL_ERROR();

    // Check the compilation status of the new shader. If compilation
    // failed, this shader file is invalid. Abort this algorithm, do not
    // continue trying to load the file. Host applications should alert the
    // user that there was a problem loading the file.

    GLint compile_status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
    CHECK_GL_ERROR();
    log_shader_log(shader);
    if (compile_status == GL_FALSE) {
        fs_emu_warning("failed to compile fragment shader");
        data->error = 1;
        return;
    }
    else {
        fs_log("compiled fragment shader successfully\n");
    }

    // Add the shader handle to the current list of shaders.

    data->shader->current_shaders = g_list_append(
            data->shader->current_shaders,
            FS_UINT_TO_POINTER(shader));

    // Take the shader-handles from the current list of shaders and link
    // them into a shader program.

    GLuint program = glCreateProgram();
    CHECK_GL_ERROR();
    if (program == 0) {
        fs_emu_warning("failed to create shader program");
        data->error = 1;
        return;
    }

    GList *link = data->shader->current_shaders;
    while (link) {
        GLuint shader = GPOINTER_TO_UINT(link->data);
        glAttachShader(program, shader);
        // schedule shader for deletion so it will be deleted when the
        // program is deleted
        glDeleteShader(shader);
        GList *temp = link;
        link = link->next;
        g_list_free_1(temp);
    }
    data->shader->current_shaders = NULL;

    glLinkProgram(program);
    CHECK_GL_ERROR();

    // Validate the new shader program. If validation failed, this shader
    // file is invalid. Abort this algorithm, do not continue trying to load
    // the file. Host applications should alert the user that there was a
    // problem loading the file.

    // Check the link status of the new shader program. If linking failed,
    // this shader file is invalid. Abort this algorithm, do not continue
    // trying to load the file. Host applications should alert the user
    // that there was a problem loading the file.

    GLint link_status;
    glGetProgramiv(program, GL_LINK_STATUS, &link_status);
    CHECK_GL_ERROR();
    if (link_status == GL_FALSE) {
        fs_emu_warning("failed to link shader pass");
        data->error = 1;
        return;
    }
    else {
        fs_log("linked shader program successfully\n");
    }

    // Create a new shader pass from the new shader program handle,
    // the value of the filter attribute of the current element, the
    // current horizontal scale method, the current horizontal scale value,
    // the current vertical scale method and the current vertical scale value.

    shader_pass *pass = g_new0(shader_pass, 1);
    pass->program = program;
    pass->ver_scale_method = cur_ver_scale_method;
    pass->ver_scale_value = cur_ver_scale_value;
    pass->hor_scale_method = cur_hor_scale_method;
    pass->hor_scale_value = cur_hor_scale_value;
    pass->filtering = FILTERING_NOTSET;
    if (data->filter) {
        if (strcmp(data->filter, "nearest") == 0) {
            pass->filtering = FILTERING_NEAREST;
        }
        else if (strcmp(data->filter, "linear") == 0) {
            pass->filtering = FILTERING_LINEAR;
        }
    }
    // Add the shader pass to the list of shader passes.
    data->shader->passes = g_list_append(data->shader->passes, pass);
}