Framebuffer::Framebuffer( uint width, uint height, uchar color, uchar depth ) { PUSHSTATE() // Determine appropriate formats InternalFormat::internal_format_t colorFormat; if ( color == 24 ) colorFormat = InternalFormat::RGB; else if ( color == 32 ) colorFormat = InternalFormat::RGBA; else throw FramebufferException(); InternalFormat::internal_format_t depthFormat; if ( depth == 8 ) depthFormat = InternalFormat::DepthComponent; else if ( depth == 16 ) depthFormat = InternalFormat::DepthComponent16; else if ( depth == 24 ) depthFormat = InternalFormat::DepthComponent24; else if ( depth == 32 ) depthFormat = InternalFormat::DepthComponent32F; else throw FramebufferException(); // Create FBO gc.Create( obj, glGenFramebuffers, glDeleteFramebuffers ); glBindFramebuffer( GL_DRAW_FRAMEBUFFER, obj ); // Create texture to hold color buffer texColor.Image2D( 0, DataType::UnsignedByte, Format::RGBA, width, height, colorFormat ); texColor.SetWrapping( GL::Wrapping::ClampEdge, GL::Wrapping::ClampEdge ); texColor.SetFilters( GL::Filter::Linear, GL::Filter::Linear ); glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0 ); // Create renderbuffer to hold depth buffer if ( depth > 0 ) { glBindTexture( GL_TEXTURE_2D, texDepth ); glTexImage2D( GL_TEXTURE_2D, 0, depthFormat, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0 ); texDepth.SetWrapping( GL::Wrapping::ClampEdge, GL::Wrapping::ClampEdge ); texDepth.SetFilters( GL::Filter::Nearest, GL::Filter::Nearest ); glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texDepth, 0 ); } // Check if ( glCheckFramebufferStatus( GL_DRAW_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) throw FramebufferException(); POPSTATE() }
/*! Create a new expression by parsing the given string. */ mapper_expr mapper_expr_new_from_string(const char *str, int input_is_float, int output_is_float, int vector_size) { const char *s = str; if (!str) return 0; stack_obj_t stack[STACK_SIZE]; int top = -1; exprnode result = 0; const char *error_message = 0; token_t tok; int i, next_token = 1; int var_allowed = 1; float oldest_samps = 0; PUSHSTATE(EXPR); PUSHSTATE(YEQUAL_EQ); PUSHSTATE(YEQUAL_Y); while (top >= 0) { if (next_token && expr_lex(&s, &tok)) {FAIL("Error in lexical analysis.");} next_token = 0; if (stack[top].type == ST_NODE) { if (top==0) SUCCESS(stack[top].node); if (stack[top-1].type == ST_STATE) { if (top >= 2 && stack[top-2].type == ST_NODE) { if (stack[top-1].type == ST_STATE && (stack[top-1].state == EXPR_RIGHT || stack[top-1].state == TERM_RIGHT || stack[top-1].state == CLOSE_PAREN)) { collapse_expr_to_left(&stack[top-2].node, stack[top].node, 1); POP(); } else if (stack[top-1].type == ST_STATE && stack[top-1].state == CLOSE_HISTINDEX) { die_unless(stack[top-2].node->tok.type == TOK_VAR, "expected VAR two-down on the stack.\n"); die_unless(!stack[top].node->next && (stack[top].node->tok.type == TOK_INT || stack[top].node->tok.type == TOK_FLOAT), "expected lonely INT or FLOAT expression on the stack.\n"); if (stack[top].node->tok.type == TOK_FLOAT) stack[top-2].node->history_index = (int)stack[top].node->tok.f; else stack[top-2].node->history_index = stack[top].node->tok.i; /* Track the oldest history reference in order * to know how much buffer needs to be * allocated for this expression. */ if (oldest_samps > stack[top-2].node->history_index) oldest_samps = stack[top-2].node->history_index; exprnode_free(stack[top].node); POP(); } else if (stack[top-1].type == ST_STATE && stack[top-1].state == CLOSE_VECTINDEX) { die_unless(stack[top-2].node->tok.type == TOK_VAR, "expected VAR two-down on the stack.\n"); die_unless(!stack[top].node->next && (stack[top].node->tok.type == TOK_INT || stack[top].node->tok.type == TOK_FLOAT), "expected lonely INT or FLOAT expression on the stack.\n"); if (stack[top].node->tok.type == TOK_FLOAT) stack[top-2].node->vector_index = (int)stack[top].node->tok.f; else stack[top-2].node->vector_index = stack[top].node->tok.i; if (stack[top-2].node->vector_index > 0) {FAIL("Vector indexing not yet implemented.");} if (stack[top-2].node->vector_index < 0 || stack[top-2].node->vector_index >= vector_size) {FAIL("Vector index outside input size.");} exprnode_free(stack[top].node); POP(); } } else { // swap the expression down the stack stack_obj_t tmp = stack[top-1]; stack[top-1] = stack[top]; stack[top] = tmp; } } #if TRACING printstack(&stack[0], top); #endif continue; } switch (stack[top].state) { case YEQUAL_Y: if (tok.type == TOK_VAR && tok.var == 'y') POP(); else {FAIL("Error in y= prefix.");} next_token = 1; break; case YEQUAL_EQ: if (tok.type == TOK_OP && tok.op == '=') { POP(); } else { {FAIL("Error in y= prefix.");} } next_token = 1; break; case EXPR: POP(); PUSHSTATE(EXPR_RIGHT); PUSHSTATE(TERM); break; case EXPR_RIGHT: if (tok.type == TOK_OP) { POP(); if (tok.op == '+' || tok.op == '-') { APPEND_OP(tok); PUSHSTATE(EXPR); next_token = 1; } } else POP(); break; case TERM: POP(); PUSHSTATE(TERM_RIGHT); PUSHSTATE(VALUE); break; case TERM_RIGHT: if (tok.type == TOK_OP) { POP(); if (tok.op == '*' || tok.op == '/' || tok.op == '%') { APPEND_OP(tok); PUSHSTATE(TERM); next_token = 1; } } else POP(); break; case VALUE: if (tok.type == TOK_INT) { POP(); PUSHEXPR(tok, 0); next_token = 1; } else if (tok.type == TOK_FLOAT) { POP(); PUSHEXPR(tok, 1); next_token = 1; } else if (tok.type == TOK_VAR) { if (var_allowed) { POP(); PUSHEXPR(tok, input_is_float); PUSHSTATE(VAR_RIGHT); next_token = 1; } else {FAIL("Unexpected variable reference.");} } else if (tok.type == TOK_OPEN_PAREN) { POP(); PUSHSTATE(CLOSE_PAREN); PUSHSTATE(EXPR); next_token = 1; } else if (tok.type == TOK_FUNC) { POP(); if (tok.func == FUNC_UNKNOWN) {FAIL("Unknown function.");} else { PUSHEXPR(tok, 1); int arity = function_table[tok.func].arity; if (arity > 0) { PUSHSTATE(CLOSE_PAREN); PUSHSTATE(EXPR); for (i=1; i < arity; i++) { PUSHSTATE(COMMA); PUSHSTATE(EXPR); } PUSHSTATE(OPEN_PAREN); } next_token = 1; } } else if (tok.type == TOK_OP && tok.op == '-') { POP(); PUSHSTATE(NEGATE); PUSHSTATE(VALUE); next_token = 1; } else {FAIL("Expected value.");} break; case NEGATE: POP(); // insert '0' before, and '-' after the expression. // set is_float according to trailing operator. if (stack[top].type == ST_NODE) { token_t t; t.type = TOK_INT; t.i = 0; exprnode e = exprnode_new(&t, 0); t.type = TOK_OP; t.op = '-'; e->next = exprnode_new(&t, 0); collapse_expr_to_left(&e, stack[top].node, 1); stack[top].node = e; } else {FAIL("Expected to negate an expression.");} break; case VAR_RIGHT: if (tok.type == TOK_OPEN_SQUARE) { POP(); PUSHSTATE(VAR_VECTINDEX); } else if (tok.type == TOK_OPEN_CURLY) { POP(); PUSHSTATE(VAR_HISTINDEX); } else POP(); break; case VAR_VECTINDEX: POP(); if (tok.type == TOK_OPEN_SQUARE) { var_allowed = 0; PUSHSTATE(CLOSE_VECTINDEX); PUSHSTATE(EXPR); next_token = 1; } break; case VAR_HISTINDEX: POP(); if (tok.type == TOK_OPEN_CURLY) { var_allowed = 0; PUSHSTATE(CLOSE_HISTINDEX); PUSHSTATE(EXPR); next_token = 1; } break; case CLOSE_VECTINDEX: if (tok.type == TOK_CLOSE_SQUARE) { var_allowed = 1; POP(); PUSHSTATE(VAR_HISTINDEX); next_token = 1; } else {FAIL("Expected ']'.");} break; case CLOSE_HISTINDEX: if (tok.type == TOK_CLOSE_CURLY) { var_allowed = 1; POP(); PUSHSTATE(VAR_VECTINDEX); next_token = 1; } else {FAIL("Expected '}'.");} break; case CLOSE_PAREN: if (tok.type == TOK_CLOSE_PAREN) { POP(); next_token = 1; break; } else {FAIL("Expected ')'.");} break; case COMMA: if (tok.type == TOK_COMMA) { POP(); // find previous expression on the stack for (i=top-1; i>=0 && stack[i].type!=ST_NODE; --i) {}; if (i>=0) { collapse_expr_to_left(&stack[i].node, stack[top].node, 0); POP(); } next_token = 1; } else {FAIL("Expected ','.");} break; case OPEN_PAREN: if (tok.type == TOK_OPEN_PAREN) { POP(); next_token = 1; } else {FAIL("Expected '('.");} break; case END: if (tok.type == TOK_END) { POP(); break; } else {FAIL("Expected END.");} default: FAIL("Unexpected parser state."); break; } #if TRACING printstack(&stack[0], top); #endif } done: if (!result) { if (error_message) printf("%s\n", error_message); goto cleanup; } // We need a limit, but this is a bit arbitrary. if (oldest_samps < -100) { trace("Expression contains history reference of %f\n", oldest_samps); goto cleanup; } // Coerce the final output if necessary exprnode e = result; while (e->next) e = e->next; if (e->is_float && !output_is_float) { token_t coerce; coerce.type = TOK_TOINT32; e->next = exprnode_new(&coerce, 0); e->next->is_float = 0; } else if (!e->is_float && output_is_float) { token_t coerce; coerce.type = TOK_TOFLOAT; e->next = exprnode_new(&coerce, 0); e->next->is_float = 1; } /* Special case: if this is a vector expression, we currently do * not completely support it. However, we can "fake" vector * operations by performing the entire expression element-wise. * In this case, we have to disallow any vector indexing, so here * we scan the compiled expression and check for it. This will be * removed in a future version. */ if (vector_size > 1) { e = result; while (e) { if (e->tok.type == TOK_VAR && e->vector_index > 0) { trace("vector indexing not yet implemented\n"); goto cleanup; } e = e->next; } } mapper_expr expr = malloc(sizeof(struct _mapper_expr)); expr->node = result; expr->vector_size = 1; expr->history_size = (int)ceilf(-oldest_samps)+1; expr->history_pos = -1; expr->input_history = calloc(1, sizeof(mapper_signal_value_t) * vector_size * expr->history_size); expr->output_history = calloc(1, sizeof(mapper_signal_value_t) * expr->history_size); return expr; cleanup: for (i=0; i<top; i++) { if (stack[i].type == ST_NODE) exprnode_free(stack[i].node); } return 0; }