<commit_before>/*
 * Copyright 2018 GoPro Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <string.h>

#include "fbo.h"
#include "format.h"
#include "glcontext.h"
#include "glincludes.h"
#include "log.h"
#include "texture.h"

static GLenum get_gl_attachment_index(GLenum format)
{
    switch (format) {
    case GL_DEPTH_COMPONENT:
    case GL_DEPTH_COMPONENT16:
    case GL_DEPTH_COMPONENT24:
    case GL_DEPTH_COMPONENT32F:
        return GL_DEPTH_ATTACHMENT;
    case GL_DEPTH_STENCIL:
    case GL_DEPTH24_STENCIL8:
    case GL_DEPTH32F_STENCIL8:
        return GL_DEPTH_STENCIL_ATTACHMENT;
    case GL_STENCIL_INDEX:
    case GL_STENCIL_INDEX8:
        return GL_STENCIL_ATTACHMENT;
    default:
        return GL_COLOR_ATTACHMENT0;
    }
}

static const GLenum depth_stencil_attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};

int ngli_fbo_init(struct fbo *fbo, struct glcontext *gl, const struct fbo_params *params)
{
    fbo->gl = gl;
    fbo->width = params->width;
    fbo->height = params->height;

    ngli_darray_init(&fbo->depth_indices, sizeof(GLenum), 0);

    GLuint fbo_id = 0;
    ngli_glGetIntegerv(gl, GL_FRAMEBUFFER_BINDING, (GLint *)&fbo_id);

    ngli_glGenFramebuffers(gl, 1, &fbo->id);
    ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo->id);

    int color_index = 0;
    for (int i = 0; i < params->nb_attachments; i++) {
        const struct texture *attachment = params->attachments[i];

        GLenum attachment_index = get_gl_attachment_index(attachment->format);
        const int is_color_attachment = attachment_index == GL_COLOR_ATTACHMENT0;
        if (is_color_attachment) {
            if (color_index >= gl->max_color_attachments) {
                LOG(ERROR, "could not attach color buffer %d (maximum %d)",
                    color_index, gl->max_color_attachments);
                ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo_id);
                return -1;
            }
            attachment_index = attachment_index + color_index++;
        }

        switch (attachment->target) {
        case GL_RENDERBUFFER:
            if (gl->backend == NGL_BACKEND_OPENGLES && gl->version < 300 && attachment_index == GL_DEPTH_STENCIL_ATTACHMENT) {
                ngli_glFramebufferRenderbuffer(gl, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, attachment->id);
                ngli_glFramebufferRenderbuffer(gl, GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, attachment->id);
                ngli_darray_push(&fbo->depth_indices, depth_stencil_attachments);
                ngli_darray_push(&fbo->depth_indices, depth_stencil_attachments + 1);
            } else {
                ngli_glFramebufferRenderbuffer(gl, GL_FRAMEBUFFER, attachment_index, GL_RENDERBUFFER, attachment->id);
                if (!is_color_attachment) {
                    if (gl->platform == NGL_PLATFORM_IOS && attachment_index == GL_DEPTH_STENCIL_ATTACHMENT) {
                        ngli_darray_push(&fbo->depth_indices, depth_stencil_attachments);
                        ngli_darray_push(&fbo->depth_indices, depth_stencil_attachments + 1);
                    } else {
                        ngli_darray_push(&fbo->depth_indices, &attachment_index);
                    }
                }
            }
            break;
        case GL_TEXTURE_2D:
            ngli_glFramebufferTexture2D(gl, GL_FRAMEBUFFER, attachment_index, GL_TEXTURE_2D, attachment->id, 0);
            break;
        default:
            ngli_assert(0);
        }
    }

    if (ngli_glCheckFramebufferStatus(gl, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        LOG(ERROR, "framebuffer %u is not complete", fbo->id);
        ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo_id);
        return -1;
    }

    ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo_id);

    return 0;
}

int ngli_fbo_bind(struct fbo *fbo)
{
    struct glcontext *gl = fbo->gl;

    ngli_glGetIntegerv(gl, GL_FRAMEBUFFER_BINDING, (GLint *)&fbo->prev_id);
    ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo->id);

    return 0;
}

int ngli_fbo_unbind(struct fbo *fbo)
{
    struct glcontext *gl = fbo->gl;

    ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo->prev_id);
    fbo->prev_id = 0;

    return 0;
}

void ngli_fbo_invalidate_depth_buffers(struct fbo *fbo)
{
    struct glcontext *gl = fbo->gl;

    if (!(gl->features & NGLI_FEATURE_INVALIDATE_SUBDATA))
        return;

    int nb_attachments = ngli_darray_count(&fbo->depth_indices);
    if (nb_attachments) {
        GLenum *attachments = ngli_darray_data(&fbo->depth_indices);
        ngli_glInvalidateFramebuffer(gl, GL_FRAMEBUFFER, nb_attachments, attachments);
    }
}

void ngli_fbo_blit(struct fbo *fbo, struct fbo *dst)
{
    struct glcontext *gl = fbo->gl;

    if (!(gl->features & NGLI_FEATURE_FRAMEBUFFER_OBJECT))
        return;

    ngli_glBindFramebuffer(gl, GL_DRAW_FRAMEBUFFER, dst->id);
    ngli_glBlitFramebuffer(gl, 0, 0, dst->width, dst->height, 0, 0, fbo->width, fbo->height,
                           GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
    ngli_glBindFramebuffer(gl, GL_DRAW_FRAMEBUFFER, fbo->id);
}

void ngli_fbo_reset(struct fbo *fbo)
{
    struct glcontext *gl = fbo->gl;
    if (!gl)
        return;

    ngli_glDeleteFramebuffers(gl, 1, &fbo->id);

    ngli_darray_reset(&fbo->depth_indices);

    memset(fbo, 0, sizeof(*fbo));
}<commit_msg>fbo: fix blit src/dst coordinates swap<commit_after>/*
 * Copyright 2018 GoPro Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <string.h>

#include "fbo.h"
#include "format.h"
#include "glcontext.h"
#include "glincludes.h"
#include "log.h"
#include "texture.h"

static GLenum get_gl_attachment_index(GLenum format)
{
    switch (format) {
    case GL_DEPTH_COMPONENT:
    case GL_DEPTH_COMPONENT16:
    case GL_DEPTH_COMPONENT24:
    case GL_DEPTH_COMPONENT32F:
        return GL_DEPTH_ATTACHMENT;
    case GL_DEPTH_STENCIL:
    case GL_DEPTH24_STENCIL8:
    case GL_DEPTH32F_STENCIL8:
        return GL_DEPTH_STENCIL_ATTACHMENT;
    case GL_STENCIL_INDEX:
    case GL_STENCIL_INDEX8:
        return GL_STENCIL_ATTACHMENT;
    default:
        return GL_COLOR_ATTACHMENT0;
    }
}

static const GLenum depth_stencil_attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};

int ngli_fbo_init(struct fbo *fbo, struct glcontext *gl, const struct fbo_params *params)
{
    fbo->gl = gl;
    fbo->width = params->width;
    fbo->height = params->height;

    ngli_darray_init(&fbo->depth_indices, sizeof(GLenum), 0);

    GLuint fbo_id = 0;
    ngli_glGetIntegerv(gl, GL_FRAMEBUFFER_BINDING, (GLint *)&fbo_id);

    ngli_glGenFramebuffers(gl, 1, &fbo->id);
    ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo->id);

    int color_index = 0;
    for (int i = 0; i < params->nb_attachments; i++) {
        const struct texture *attachment = params->attachments[i];

        GLenum attachment_index = get_gl_attachment_index(attachment->format);
        const int is_color_attachment = attachment_index == GL_COLOR_ATTACHMENT0;
        if (is_color_attachment) {
            if (color_index >= gl->max_color_attachments) {
                LOG(ERROR, "could not attach color buffer %d (maximum %d)",
                    color_index, gl->max_color_attachments);
                ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo_id);
                return -1;
            }
            attachment_index = attachment_index + color_index++;
        }

        switch (attachment->target) {
        case GL_RENDERBUFFER:
            if (gl->backend == NGL_BACKEND_OPENGLES && gl->version < 300 && attachment_index == GL_DEPTH_STENCIL_ATTACHMENT) {
                ngli_glFramebufferRenderbuffer(gl, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, attachment->id);
                ngli_glFramebufferRenderbuffer(gl, GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, attachment->id);
                ngli_darray_push(&fbo->depth_indices, depth_stencil_attachments);
                ngli_darray_push(&fbo->depth_indices, depth_stencil_attachments + 1);
            } else {
                ngli_glFramebufferRenderbuffer(gl, GL_FRAMEBUFFER, attachment_index, GL_RENDERBUFFER, attachment->id);
                if (!is_color_attachment) {
                    if (gl->platform == NGL_PLATFORM_IOS && attachment_index == GL_DEPTH_STENCIL_ATTACHMENT) {
                        ngli_darray_push(&fbo->depth_indices, depth_stencil_attachments);
                        ngli_darray_push(&fbo->depth_indices, depth_stencil_attachments + 1);
                    } else {
                        ngli_darray_push(&fbo->depth_indices, &attachment_index);
                    }
                }
            }
            break;
        case GL_TEXTURE_2D:
            ngli_glFramebufferTexture2D(gl, GL_FRAMEBUFFER, attachment_index, GL_TEXTURE_2D, attachment->id, 0);
            break;
        default:
            ngli_assert(0);
        }
    }

    if (ngli_glCheckFramebufferStatus(gl, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        LOG(ERROR, "framebuffer %u is not complete", fbo->id);
        ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo_id);
        return -1;
    }

    ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo_id);

    return 0;
}

int ngli_fbo_bind(struct fbo *fbo)
{
    struct glcontext *gl = fbo->gl;

    ngli_glGetIntegerv(gl, GL_FRAMEBUFFER_BINDING, (GLint *)&fbo->prev_id);
    ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo->id);

    return 0;
}

int ngli_fbo_unbind(struct fbo *fbo)
{
    struct glcontext *gl = fbo->gl;

    ngli_glBindFramebuffer(gl, GL_FRAMEBUFFER, fbo->prev_id);
    fbo->prev_id = 0;

    return 0;
}

void ngli_fbo_invalidate_depth_buffers(struct fbo *fbo)
{
    struct glcontext *gl = fbo->gl;

    if (!(gl->features & NGLI_FEATURE_INVALIDATE_SUBDATA))
        return;

    int nb_attachments = ngli_darray_count(&fbo->depth_indices);
    if (nb_attachments) {
        GLenum *attachments = ngli_darray_data(&fbo->depth_indices);
        ngli_glInvalidateFramebuffer(gl, GL_FRAMEBUFFER, nb_attachments, attachments);
    }
}

void ngli_fbo_blit(struct fbo *fbo, struct fbo *dst)
{
    struct glcontext *gl = fbo->gl;

    if (!(gl->features & NGLI_FEATURE_FRAMEBUFFER_OBJECT))
        return;

    ngli_glBindFramebuffer(gl, GL_DRAW_FRAMEBUFFER, dst->id);
    ngli_glBlitFramebuffer(gl, 0, 0, fbo->width, fbo->height, 0, 0, dst->width, dst->height,
                           GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
    ngli_glBindFramebuffer(gl, GL_DRAW_FRAMEBUFFER, fbo->id);
}

void ngli_fbo_reset(struct fbo *fbo)
{
    struct glcontext *gl = fbo->gl;
    if (!gl)
        return;

    ngli_glDeleteFramebuffers(gl, 1, &fbo->id);

    ngli_darray_reset(&fbo->depth_indices);

    memset(fbo, 0, sizeof(*fbo));
}
{'fraction_non_alphanumeric': 0.09564724000972684, 'fraction_numerical': 0.008105698305909055, 'mean_word_length': 3.1140380126708904, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3462531', 'n_tokens_mistral': 4253, 'n_tokens_neox': 4087, 'n_words': 881}