ResizeContext Resize::get_context(Alloc &alloc, PixelType type) const { ResizeContext ctx{}; if (!m_skip_h && !m_skip_v) { double xscale = (double)m_dst_width / (double)m_src_width; double yscale = (double)m_dst_height / (double)m_src_height; bool h_first = resize_h_first(xscale, yscale); ctx.impl1 = h_first ? m_impl_h.get() : m_impl_v.get(); ctx.impl2 = h_first ? m_impl_v.get() : m_impl_h.get(); ctx.tmp_width = h_first ? m_dst_width : m_src_width; ctx.tmp_height = h_first ? m_src_height : m_dst_height; ctx.in_buffering1 = std::min(ctx.impl1->input_buffering(type), m_src_height); ctx.in_buffering2 = std::min(ctx.impl2->input_buffering(type), ctx.tmp_height); ctx.out_buffering1 = ctx.impl1->output_buffering(type); ctx.out_buffering2 = ctx.impl2->output_buffering(type); ctx.src_border_buf = alloc_line_buffer(alloc, ctx.in_buffering1, m_src_width, type); ctx.dst_border_buf = alloc_line_buffer(alloc, ctx.out_buffering2, m_dst_width, type); ctx.tmp_buf = alloc_line_buffer(alloc, ctx.out_buffering1 + ctx.in_buffering2 - 1, ctx.tmp_width, type); ctx.tmp_data = alloc.allocate(std::max(ctx.impl1->tmp_size(type, ctx.tmp_width), ctx.impl2->tmp_size(type, m_dst_width))); } else if (!(m_skip_h && m_skip_v)) { ctx.impl1 = m_impl_h ? m_impl_h.get() : m_impl_v.get(); ctx.in_buffering1 = std::min(ctx.impl1->input_buffering(type), m_src_height); ctx.out_buffering1 = ctx.impl1->output_buffering(type); ctx.src_border_buf = alloc_line_buffer(alloc, ctx.in_buffering1, m_src_width, type); ctx.dst_border_buf = alloc_line_buffer(alloc, ctx.out_buffering1, m_dst_width, type); ctx.tmp_data = alloc.allocate(ctx.impl1->tmp_size(type, m_dst_width)); } return ctx; }
void tty_emit(int job_id, int is_stderr, int sort_key, const char *data, int len) { line_buffer *buf = NULL; td_mutex_lock_or_die(&linelock); while (len > 0) { /* Wait for a line buffer to become available, or for the tty to become free. */ for (;;) { /* If we already have the tty, or we can get it: break */ if (-1 == printing_job || job_id == printing_job) break; /* If we can allocate a buffer: break */ if (NULL != (buf = alloc_line_buffer())) break; /* Otherwise wait */ pthread_cond_wait(&can_print, &linelock); } if (-1 == printing_job) { /* Let this job own the output channel */ TTY_PRINTF(("job %d is taking the tty\n", job_id)); printing_job = job_id; flush_output_queue(job_id); } else if (job_id != printing_job) { assert(buf); } if (!buf) { /* This thread owns the TTY, so just print. We don't need to keep the * mutex locked as this job will not finsh and reset the currently * printing job until later. Releasing the mutex now means other * threads can come in and buffer their data. */ td_mutex_unlock_or_die(&linelock); TTY_PRINTF(("copying %d bytes of data from job_id %d, stderr=%d, sort_key %d\n", len, job_id, is_stderr, sort_key)); write(is_stderr ? STDERR_FILENO : STDOUT_FILENO, data, strlen(data)); return; /* finish the loop immediately */ } else { /* We can't print this data as we don't own the TTY so we buffer it. */ TTY_PRINTF(("buffering %d bytes of data from job_id %d, stderr=%d, sort_key %d\n", len, job_id, is_stderr, sort_key)); /* PERF: Could release mutex around this memcpy, not sure if it's a win. */ buf->job_id = job_id; buf->sort_key = sort_key; buf->len = len > LINEBUF_SIZE - 1 ? LINEBUF_SIZE - 1 : len; buf->is_stderr = is_stderr; memcpy(buf->data, data, buf->len); buf->data[buf->len] = '\0'; len -= buf->len; data += buf->len; /* Queue this line for output */ queued_linebufs[queued_linebuf_count++] = buf; } } td_mutex_unlock_or_die(&linelock); return; }